diff --git a/.babelrc b/.babelrc deleted file mode 100644 index aff1f600..00000000 --- a/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ["atomic-router/babel-preset"], - "plugins": ["effector/babel-plugin"] -} diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..e6f28b0b --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +reatom-form diff --git a/.eslintrc.json b/.eslintrc.json index 6cfe74be..6995f5ca 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,13 +7,11 @@ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:sonarjs/recommended", - "plugin:effector/recommended", - "plugin:effector/react", - "plugin:effector/scope", "plugin:import/recommended", "plugin:import/warnings", "plugin:import/typescript", "plugin:boundaries/recommended", + "plugin:@reatom/recommended", "airbnb", "prettier" ], @@ -25,7 +23,27 @@ "ecmaVersion": "latest", "sourceType": "module" }, - "plugins": ["react", "@typescript-eslint", "effector"], + "plugins": ["react", "@typescript-eslint", "@reatom", "boundaries"], + "settings": { + "import/resolver": "typescript", + "boundaries/elements": [ + { "type": "app", "pattern": "@/app/*" }, + { "type": "pages", "pattern": "@/pages/*" }, + { "type": "widgets", "pattern": "@/widgets/*" }, + { "type": "features", "pattern": "@/features/*" }, + { + "type": "@x", + "pattern": "@/entities/*/@x/*.ts", + "mode": "file" + }, + { + "type": "entities", + "pattern": "@/entities/*" + }, + { "type": "shared", "pattern": "@/shared/*" } + ], + "boundaries/ignore": ["**/*.spec.*"] + }, "rules": { /* STANDARD */ "no-use-before-define": "off", @@ -85,7 +103,11 @@ }, { "message": "Private imports are prohibited, use public imports instead", - "group": ["@/entities/*/**"] + "group": [ + "@/entities/*/**", + "!@/entities/*/@x", + "!@/entities/*/@x/*" + ] }, { "message": "Private imports are prohibited, use public imports instead", @@ -130,6 +152,7 @@ "react/no-unused-prop-types": "off", "react/no-array-index-key": "off", "react/react-in-jsx-scope": "off", + "react/jsx-no-bind": "off", /* IMPORT */ "import/order": [ @@ -149,6 +172,11 @@ "position": "after", "pattern": "@/features/**" }, + { + "group": "internal", + "position": "after", + "pattern": "@/entities/*/@x/*.ts" + }, { "group": "internal", "position": "after", @@ -182,39 +210,33 @@ ], "import/no-unresolved": 0, "import/prefer-default-export": "off", + "import/export": "off", /* BOUNDARIES */ "boundaries/element-types": [ - "warn", + "error", { "default": "disallow", "rules": [ { - "from": "@/app", - "allow": [ - "@/pages", - "@/widgets", - "@/features", - "@/entities", - "@/shared" - ] + "from": "app", + "allow": ["pages", "widgets", "features", "entities", "shared"] }, { - "from": "@/pages", - "allow": ["@/widgets", "@/features", "@/entities", "@/shared"] + "from": "pages", + "allow": ["widgets", "features", "entities", "shared"] }, { - "from": "@/widgets", - "allow": ["@/features", "@/entities", "@/shared"] + "from": "widgets", + "allow": ["features", "entities", "shared"] }, - { "from": "@/features", "allow": ["@/entities", "@/shared"] }, - { "from": "@/entities", "allow": ["@/shared"] }, - { "from": "@/shared", "allow": ["@/shared"] } + { "from": "features", "allow": ["entities", "shared"] }, + { "from": "entities", "allow": ["@x", "shared"] }, + { "from": "shared", "allow": ["shared"] } ] } ], - /* TS */ "@typescript-eslint/no-unused-vars": ["error"], "@typescript-eslint/no-empty-interface": ["off"], "@typescript-eslint/no-explicit-any": "warn" diff --git a/.lintstagedrc.json b/.lintstagedrc.json index 7acd0f5c..d7414166 100644 --- a/.lintstagedrc.json +++ b/.lintstagedrc.json @@ -5,6 +5,6 @@ ], "*.css": [ "prettier --write --ignore-unknown --config ./.prettierrc --ignore-path ./.prettierignore", - "stylelint --fix -c ./configs/styles/.stylelintrc.json" + "stylelint --fix -c ./.stylelintrc.json" ] } diff --git a/.stylelintrc.json b/.stylelintrc.json index a91b6eb4..1ee1afca 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -12,16 +12,18 @@ "color-format/format": { "format": "hsl" }, - "media-feature-range-notation": "prefix", + "media-feature-range-notation": "context", "plugin/z-index-value-constraint": { - "min": -1, "max": 10000 }, "pitcher/no-nested-media": true, - "plugin/no-low-performance-animation-properties": true + "plugin/no-low-performance-animation-properties": [ + true, + { "ignoreProperties": ["box-shadow"] } + ] }, "ignoreFiles": ["**/*.[jt]sx?", "**/third-party/*", "**/PlanEditor/*"] } diff --git a/README.md b/README.md index b87cb004..181674a8 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,5 @@ -# Getting Started with Create React App +@todo +Think about [atomization](https://www.reatom.dev/recipes/atomization/) -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). - -## Available Scripts - -In the project directory, you can run: - -### `npm start` - -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will reload if you make edits.\ -You will also see any lint errors in the console. - -### `npm test` - -Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. - -### `npm run build` - -Builds the app for production to the `build` folder.\ -It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.\ -Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `npm run eject` - -**Note: this is a one-way operation. Once you `eject`, you can’t go back!** - -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. - -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). +@todo +Think about scope, DI and its react integration diff --git a/configs/tests/setup.ts b/configs/tests/setup.ts index 56d2268e..4bc32fa7 100644 --- a/configs/tests/setup.ts +++ b/configs/tests/setup.ts @@ -1,4 +1,5 @@ import { expect, afterEach, beforeAll, afterAll, vi } from 'vitest'; +import { resetDefaultInjector } from 'bunshi'; import { cleanup } from '@testing-library/react'; import * as matchers from '@testing-library/jest-dom/matchers'; import { @@ -29,6 +30,7 @@ afterEach(() => { cleanup(); server.resetHandlers(); cleanupMatchMedia(); + resetDefaultInjector(); }); afterAll(() => { @@ -37,3 +39,4 @@ afterAll(() => { window.MediaQueryListEvent = MediaQueryListEvent; window.matchMedia = matchMedia; +window.scrollTo = vi.fn(); diff --git a/package-lock.json b/package-lock.json index 256d82dd..fcb2e1dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,16 @@ "@fontsource/roboto": "^5.0.8", "@mui/icons-material": "^5.14.14", "@mui/lab": "^5.0.0-alpha.108", - "@mui/material": "^5.14.14", + "@mui/material": "^5.16.14", "@mui/x-date-pickers": "^6.16.2", + "@reatom/framework": "^3.4.58", + "@reatom/npm-react": "^3.10.5", + "@reatom/persist": "^3.4.1", + "@reatom/url": "^3.8.0", "@withease/web-api": "^1.0.1", "atomic-router": "^0.8.0", "atomic-router-react": "^0.8.5", + "bunshi": "^2.1.5", "classnames": "^2.3.1", "compose-function": "^3.0.3", "dayjs": "^1.11.10", @@ -34,18 +39,21 @@ "i18next-http-backend": "^2.2.2", "joi": "^17.11.0", "ky": "^1.1.0", - "patronum": "^1.20.0", + "path-to-regexp": "^8.2.0", + "query-string": "^9.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-i18next": "^13.3.1", - "runtypes": "^6.7.0" + "react-use": "^17.6.0", + "runtypes": "^6.7.0", + "zod": "^3.24.1" }, "devDependencies": { - "@babel/cli": "^7.23.0", - "@babel/core": "^7.23.2", "@faker-js/faker": "^8.4.1", "@playwright/test": "^1.40.1", - "@rollup/plugin-babel": "^6.0.4", + "@reatom/devtools": "^0.9.2", + "@reatom/eslint-plugin": "^3.4.3", + "@reatom/testing": "^3.4.8", "@testing-library/jest-dom": "^6.4.6", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.5.2", @@ -61,8 +69,8 @@ "eslint": "^8.51.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-boundaries": "^3.4.0", - "eslint-plugin-effector": "^0.11.0", "eslint-plugin-import": "^2.28.1", "eslint-plugin-sonarjs": "^0.21.0", "husky": "^8.0.3", @@ -70,6 +78,7 @@ "lint-staged": "^15.0.2", "mock-match-media": "^0.4.3", "msw": "^2.3.1", + "prettier": "^3.4.2", "stylelint": "^16.9.0", "stylelint-color-format": "^1.1.0", "stylelint-config-clean-order": "^6.1.0", @@ -114,41 +123,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/cli": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.23.0.tgz", - "integrity": "sha512-17E1oSkGk2IwNILM4jtfAvgjt+ohmpfBky8aLerUfYZhiPNg7ca+CRCxZn8QDxwNhV/upsc2VHBCqGFIR+iBfA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "commander": "^4.0.1", - "convert-source-map": "^2.0.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.2.0", - "make-dir": "^2.1.0", - "slash": "^2.0.0" - }, - "bin": { - "babel": "bin/babel.js", - "babel-external-helpers": "bin/babel-external-helpers.js" - }, - "engines": { - "node": ">=6.9.0" - }, - "optionalDependencies": { - "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", - "chokidar": "^3.4.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/cli/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -1774,9 +1748,10 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -1990,17 +1965,30 @@ } }, "node_modules/@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", - "dependencies": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, + "node_modules/@emotion/cache/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/cache/node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, "node_modules/@emotion/hash": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", @@ -2055,9 +2043,10 @@ } }, "node_modules/@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" }, "node_modules/@emotion/styled": { "version": "11.11.0", @@ -2095,9 +2084,10 @@ } }, "node_modules/@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" }, "node_modules/@emotion/weak-memoize": { "version": "0.3.1", @@ -2560,19 +2550,21 @@ } }, "node_modules/@farfetched/core": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@farfetched/core/-/core-0.10.4.tgz", - "integrity": "sha512-sNhsuTL5/DPrpgp7JLN3rKJRxX6PHHG0h2Xlq4JjS2BzOGoJC/SB5iEr3kJyZLN4tjdXa2C0G/L7awf6sPh/4g==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@farfetched/core/-/core-0.10.6.tgz", + "integrity": "sha512-WSnQjftZ6ZfCFq+SOLvJpc52+xN4ND5azPPcuwOcygSZhKWs+P5wNH9WNpJ0KdP9ExOuol3JITze5LK2hLh+3g==", + "license": "MIT", "peerDependencies": { "effector": "^22.5.0" } }, "node_modules/@farfetched/runtypes": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@farfetched/runtypes/-/runtypes-0.10.4.tgz", - "integrity": "sha512-TRT6AfgFnwBQG3pjjMRC6UBlJ4DbNSvKILajINIJVhgt/9mmxlc8Mt+PObhpm9r0hhscPuLvsmBDKNIUk6UhnA==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@farfetched/runtypes/-/runtypes-0.10.6.tgz", + "integrity": "sha512-c7+WfJXi1eKy98B2ysaEgaDQMKIQB7dPoU21vB6fwDWD8hxU45z8/eUpRMA7DzRXZZWIytF8Rt0tMvMshL476g==", + "license": "MIT", "peerDependencies": { - "@farfetched/core": "0.10.4", + "@farfetched/core": "0.10.6", "runtypes": "^6.6.0" } }, @@ -2618,12 +2610,14 @@ "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" }, "node_modules/@hapi/topo": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.0.0" } @@ -2929,8 +2923,7 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -3001,12 +2994,13 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.14.tgz", - "integrity": "sha512-Rw/xKiTOUgXD8hdKqj60aC6QcGprMipG7ne2giK6Mz7b4PlhL/xog9xLeclY3BxsRLkZQ05egFnIEY1CSibTbw==", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.14.tgz", + "integrity": "sha512-sbjXW+BBSvmzn61XyTMun899E7nGPTXwqD9drm1jBUAvWEhJpPFIRxwQQiATWZnd9rvdxtnhhdsDxEGWI0jxqA==", + "license": "MIT", "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" } }, "node_modules/@mui/icons-material": { @@ -3076,21 +3070,22 @@ } }, "node_modules/@mui/material": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.14.tgz", - "integrity": "sha512-cAmCwAHFQXxb44kWbVFkhKATN8tACgMsFwrXo8ro6WzYW73U/qsR5AcCiJIhCyYYg+gcftfkmNcpRaV3JjhHCg==", - "dependencies": { - "@babel/runtime": "^7.23.1", - "@mui/base": "5.0.0-beta.20", - "@mui/core-downloads-tracker": "^5.14.14", - "@mui/system": "^5.14.14", - "@mui/types": "^7.2.6", - "@mui/utils": "^5.14.13", - "@types/react-transition-group": "^4.4.7", - "clsx": "^2.0.0", - "csstype": "^3.1.2", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.14.tgz", + "integrity": "sha512-eSXQVCMKU2xc7EcTxe/X/rC9QsV2jUe8eLM3MUCPYbo6V52eCE436akRIvELq/AqZpxx2bwkq7HC0cRhLB+yaw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/core-downloads-tracker": "^5.16.14", + "@mui/system": "^5.16.14", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.14", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", "prop-types": "^15.8.1", - "react-is": "^18.2.0", + "react-is": "^19.0.0", "react-transition-group": "^4.4.5" }, "engines": { @@ -3098,14 +3093,14 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -3119,52 +3114,29 @@ } } }, - "node_modules/@mui/material/node_modules/@mui/base": { - "version": "5.0.0-beta.20", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.20.tgz", - "integrity": "sha512-CS2pUuqxST7ch9VNDCklRYDbJ3rru20Tx7na92QvVVKfu3RL4z/QLuVIc8jYGsdCnauMaeUSlFNLAJNb0yXe6w==", - "dependencies": { - "@babel/runtime": "^7.23.1", - "@floating-ui/react-dom": "^2.0.2", - "@mui/types": "^7.2.6", - "@mui/utils": "^5.14.13", - "@popperjs/core": "^2.11.8", - "clsx": "^2.0.0", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, "node_modules/@mui/material/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==", + "license": "MIT" + }, "node_modules/@mui/private-theming": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.14.tgz", - "integrity": "sha512-n77au3CQj9uu16hak2Y+rvbGSBaJKxziG/gEbOLVGrAuqZ+ycVSkorCfN6Y/4XgYOpG/xvmuiY3JwhAEOzY3iA==", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.14.tgz", + "integrity": "sha512-12t7NKzvYi819IO5IapW2BcR33wP/KAVrU8d7gLhGHoAmhDxyXlRoKiRij3TOD8+uzk0B6R9wHUNKi4baJcRNg==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.1", - "@mui/utils": "^5.14.13", + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.16.14", "prop-types": "^15.8.1" }, "engines": { @@ -3172,11 +3144,11 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -3185,13 +3157,14 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.14.tgz", - "integrity": "sha512-sF3DS2PVG+cFWvkVHQQaGFpL1h6gSwOW3L91pdxPLQDHDZ5mZ/X0SlXU5XA+WjypoysG4urdAQC7CH/BRvUiqg==", - "dependencies": { - "@babel/runtime": "^7.23.1", - "@emotion/cache": "^11.11.0", - "csstype": "^3.1.2", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.14.tgz", + "integrity": "sha512-UAiMPZABZ7p8mUW4akDV6O7N3+4DatStpXMZwPlt+H/dA0lt67qawN021MNND+4QTpjaiMYxbhKZeQcyWCbuKw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.13.5", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { @@ -3199,12 +3172,12 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -3216,17 +3189,18 @@ } }, "node_modules/@mui/system": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.14.tgz", - "integrity": "sha512-y4InFmCgGGWXnz+iK4jRTWVikY0HgYnABjz4wgiUgEa2W1H8M4ow+27BegExUWPkj4TWthQ2qG9FOGSMtI+PKA==", - "dependencies": { - "@babel/runtime": "^7.23.1", - "@mui/private-theming": "^5.14.14", - "@mui/styled-engine": "^5.14.13", - "@mui/types": "^7.2.6", - "@mui/utils": "^5.14.13", - "clsx": "^2.0.0", - "csstype": "^3.1.2", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.14.tgz", + "integrity": "sha512-KBxMwCb8mSIABnKvoGbvM33XHyT+sN0BzEBG+rsSc0lLQGzs7127KWkCA6/H8h6LZ00XpBEME5MAj8mZLiQ1tw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.16.14", + "@mui/styled-engine": "^5.16.14", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.14", + "clsx": "^2.1.0", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { @@ -3234,13 +3208,13 @@ }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@emotion/react": { @@ -3255,19 +3229,21 @@ } }, "node_modules/@mui/system/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/@mui/types": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.6.tgz", - "integrity": "sha512-7sjLQrUmBwufm/M7jw/quNiPK/oor2+pGUQP2CULRcFCArYTq78oJ3D5esTaL0UMkXKJvDqXn6Ike69yAOBQng==", + "version": "7.2.21", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.21.tgz", + "integrity": "sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==", + "license": "MIT", "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -3276,25 +3252,28 @@ } }, "node_modules/@mui/utils": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.14.tgz", - "integrity": "sha512-3AKp8uksje5sRfVrtgG9Q/2TBsHWVBUtA0NaXliZqGcXo8J+A+Agp0qUW2rJ+ivgPWTCCubz9FZVT2IQZ3bGsw==", - "dependencies": { - "@babel/runtime": "^7.23.1", - "@types/prop-types": "^15.7.7", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.14.tgz", + "integrity": "sha512-wn1QZkRzSmeXD1IguBVvJJHV3s6rxJrfb6YuC9Kk6Noh9f8Fb54nUs5JRkKm+BOerRhj5fLg05Dhx/H3Ofb8Mg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", "prop-types": "^15.8.1", - "react-is": "^18.2.0" + "react-is": "^19.0.0" }, "engines": { "node": ">=12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/mui" + "url": "https://opencollective.com/mui-org" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -3302,6 +3281,21 @@ } } }, + "node_modules/@mui/utils/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==", + "license": "MIT" + }, "node_modules/@mui/x-date-pickers": { "version": "6.16.2", "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.16.2.tgz", @@ -3406,13 +3400,6 @@ "node": ">=6" } }, - "node_modules/@nicolo-ribaudo/chokidar-2": { - "version": "2.1.8-no-fsevents.3", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", - "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", - "dev": true, - "optional": true - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3448,6 +3435,16 @@ "node": ">= 8" } }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, "node_modules/@open-draft/deferred-promise": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", @@ -3504,54 +3501,160 @@ "url": "https://opencollective.com/popperjs" } }, - "node_modules/@rollup/plugin-babel": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz", - "integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==", + "node_modules/@reatom/async": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@reatom/async/-/async-3.16.5.tgz", + "integrity": "sha512-vUEqXFg2PX8JsRJ8i7SB2RhXf/U3p/PwBOU2QVJNhX8DSamhyu+OIiKTxvOky2lvW3rIFOWy0ATpSLn6fh1pkw==", + "license": "MIT", + "dependencies": { + "@reatom/core": "^3.5.0", + "@reatom/effects": "^3.10.0", + "@reatom/hooks": "^3.2.0", + "@reatom/primitives": "^3.5.0", + "@reatom/utils": "^3.11.0" + } + }, + "node_modules/@reatom/core": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@reatom/core/-/core-3.9.3.tgz", + "integrity": "sha512-Ts0R41475+38HhTXFUWuYgxjE90jmZMMp5yvBONhGMYLyPIDtG/zJUmivSBwXtVOI5VYeiRW6T4VUkX7ZjnDGg==", + "license": "MIT" + }, + "node_modules/@reatom/devtools": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@reatom/devtools/-/devtools-0.9.2.tgz", + "integrity": "sha512-38BAClse/ENGe8S4fpQN8J8d0I47EWASUJopF9HLp9U8nFq9/Tox6pEv9rWmaqrLgy0euN8jZOQmJja+UYAz3A==", "dev": true, + "license": "MIT" + }, + "node_modules/@reatom/effects": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@reatom/effects/-/effects-3.11.1.tgz", + "integrity": "sha512-JhEB99+Wklfkg0kpV8sKvf1tP+16DaUXOaRYW1yxrHBleQ4WgOIO7j0hHqybmhMqJ/qS7Rcs3l8X0NBaH2bRJg==", + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@rollup/pluginutils": "^5.0.1" - }, - "engines": { - "node": ">=14.0.0" + "@reatom/core": "^3.2.0", + "@reatom/utils": "^3.5.0" + } + }, + "node_modules/@reatom/eslint-plugin": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@reatom/eslint-plugin/-/eslint-plugin-3.4.3.tgz", + "integrity": "sha512-2LelP4G1FXq+89pmWfKyNLV7GtxmmiHJfl2vac9oJU7lT+eqvmWi4Pd0duAJhWTLxvg9g5S1SLeGQ7tAw/gxeg==", + "dev": true + }, + "node_modules/@reatom/framework": { + "version": "3.4.58", + "resolved": "https://registry.npmjs.org/@reatom/framework/-/framework-3.4.58.tgz", + "integrity": "sha512-iHKtf2N+57Uf6qQb/3rxij3pew/5LI7EliIuQTSgfmV15FxJktGDl9Vxj3KhEzW01XwnJBS7VRijuwS/Hz3Wvg==", + "license": "MIT", + "dependencies": { + "@reatom/async": "^3.16.5", + "@reatom/core": "^3.9.3", + "@reatom/effects": "^3.11.1", + "@reatom/hooks": "^3.6.0", + "@reatom/lens": "^3.11.6", + "@reatom/logger": "^3.8.4", + "@reatom/primitives": "^3.7.3", + "@reatom/utils": "^3.11.2" + } + }, + "node_modules/@reatom/hooks": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@reatom/hooks/-/hooks-3.6.0.tgz", + "integrity": "sha512-N3rqueSYvbQmuC2M2arF5Y7FHBK/rujK/gXXrVTTxXsetHMbwJAs7mxSB5a21s3eTHfCeOiuFCa8/qP7YL3ZVg==", + "dependencies": { + "@reatom/core": "^3.2.0", + "@reatom/effects": "^3.7.0", + "@reatom/utils": "^3.3.0" + } + }, + "node_modules/@reatom/lens": { + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/@reatom/lens/-/lens-3.11.6.tgz", + "integrity": "sha512-kzsIq6dI5UKo4/aytBiIeSAXFVbWQ4ScrsNyJK7l47BE9COvetBbugwGhvHhLdLjrPoZMEadY09Ime8NglDt5A==", + "license": "MIT", + "dependencies": { + "@reatom/core": "^3.4.0", + "@reatom/effects": "^3.2.0", + "@reatom/hooks": "^3.3.1", + "@reatom/primitives": "^3.6.0", + "@reatom/utils": "^3.1.0" + } + }, + "node_modules/@reatom/logger": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/@reatom/logger/-/logger-3.8.4.tgz", + "integrity": "sha512-MOz8Td1eZV+kU4QpkZXAdO9qFtGjqpm40crIlMNweDtOH7GgUmV2oKgOXRORQzYbeGHVMlQHG4J5iPeEQdM7KA==", + "dependencies": { + "@reatom/core": "^3.8.1", + "@reatom/utils": "^3.9.0" + } + }, + "node_modules/@reatom/npm-react": { + "version": "3.10.5", + "resolved": "https://registry.npmjs.org/@reatom/npm-react/-/npm-react-3.10.5.tgz", + "integrity": "sha512-TV86OP14sTY/JC9xSwTmYEmFu2J5mdKyezXKY2z6XuxXTGR+bNg37rxyZvPBwNigooAqlYfRrnxoPHpL8WP8fw==", + "license": "MIT", + "dependencies": { + "@reatom/core": "^3.5.0", + "@reatom/effects": "^3.7.3", + "@reatom/lens": "^3.1.0", + "@reatom/utils": "^3.9.0", + "use-sync-external-store": "^1.2.0" }, "peerDependencies": { - "@babel/core": "^7.0.0", - "@types/babel__core": "^7.1.9", - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "@types/babel__core": { - "optional": true - }, - "rollup": { - "optional": true - } + "react": ">=16.8.0" + } + }, + "node_modules/@reatom/persist": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@reatom/persist/-/persist-3.4.1.tgz", + "integrity": "sha512-LM3JriTJNSH1EluVcvW9ik7DK5oa0NeIgkz8rIGvVk/c9ZIqp0Olthc/WEB5qNNDdzZMrebGRFiHRM2iO5/T6A==", + "dependencies": { + "@reatom/core": "^3.3.0", + "@reatom/hooks": "^3.4.0", + "@reatom/lens": "^3.4.0", + "@reatom/utils": "^3.4.0" + } + }, + "node_modules/@reatom/primitives": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@reatom/primitives/-/primitives-3.7.3.tgz", + "integrity": "sha512-HzG2aoGzE2W410ZSqnT8hd21Xd+bNMIkN03tq7dWgZ4OAZKawVnxdeB8bHu+oA5ppxICfrY0HtPUUeQTbvxfgQ==", + "dependencies": { + "@reatom/core": "^3.1.1", + "@reatom/utils": "^3.1.1" } }, - "node_modules/@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "node_modules/@reatom/testing": { + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/@reatom/testing/-/testing-3.4.8.tgz", + "integrity": "sha512-9LtyEiQPgawYF6nQPXJB2LBx8ZWV92MJFL4PLLWW7L73a9Bbs4v3qnYlvT9dtLZGsxAEYHkxG2EAEg5Qrq8Ytw==", "dev": true, + "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } + "@reatom/core": "^3.5.0", + "@reatom/persist": "^3.3.0" + } + }, + "node_modules/@reatom/url": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@reatom/url/-/url-3.8.0.tgz", + "integrity": "sha512-BlrF+xdGZ4x2D6LsGQRTG648TeQ+cNyulIh4SbROfDYPDBzgfHEvmAwT3qPWFoP8VR1CNhwujpnSOtUlYIi3hQ==", + "dependencies": { + "@reatom/core": "^3.5.0", + "@reatom/effects": "^3.7.0", + "@reatom/hooks": "^3.4.0", + "@reatom/utils": "^3.4.0" } }, + "node_modules/@reatom/utils": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@reatom/utils/-/utils-3.11.2.tgz", + "integrity": "sha512-4xeSI8mQ3OEg0cUFYuQu3EMe4NJm2NKggImIV3Lm1ApIPue5F9rJ0geQ30BEAixDiMb8XUuEL5Hlzy1uuOqkQQ==", + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.18.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", @@ -3760,10 +3863,18 @@ "win32" ] }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.0.0" } @@ -3771,12 +3882,14 @@ "node_modules/@sideway/formula": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" }, "node_modules/@sideway/pinpoint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" }, "node_modules/@sinclair/typebox": { "version": "0.27.8", @@ -4135,6 +4248,12 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/js-cookie": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", + "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==", + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.14", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", @@ -4145,7 +4264,8 @@ "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/mute-stream": { "version": "0.0.4", @@ -4171,9 +4291,10 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "node_modules/@types/prop-types": { - "version": "15.7.9", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", - "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==" + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "license": "MIT" }, "node_modules/@types/react": { "version": "18.2.31", @@ -4195,10 +4316,11 @@ } }, "node_modules/@types/react-transition-group": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.8.tgz", - "integrity": "sha512-QmQ22q+Pb+HQSn04NL3HtrqHwYMf4h3QKArOy5F8U5nEVMaihBs3SR10WiOM1iwPz5jIo8x/u11al+iEGZZrvg==", - "dependencies": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { "@types/react": "*" } }, @@ -4750,13 +4872,20 @@ } }, "node_modules/@withease/web-api": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@withease/web-api/-/web-api-1.0.1.tgz", - "integrity": "sha512-KC+6ueVd1rEpLvMN7uXHa7E5TKdv7MxIhEAAs8tjAgmKxkUgranpsrjU2ZlwHGimuc98Z428/n+zgldZE3nIMg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@withease/web-api/-/web-api-1.3.0.tgz", + "integrity": "sha512-ULQu1yOoKDom7kGNg2KHeb3OJm09CbNRBZfJ/H9Mpuwia7Cydw8o0vHQEtDFyPmwYm7OIhCNEw/ILZUHzNJCQQ==", + "license": "MIT", "peerDependencies": { - "effector": "^22.5.0" + "effector": "^22.5.0 || ^23.0.0" } }, + "node_modules/@xobotyi/scrollbar-width": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", + "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==", + "license": "MIT" + }, "node_modules/acorn": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", @@ -4904,28 +5033,34 @@ "integrity": "sha512-fExL2kFDC1Q2DUOx3whE/9KoN66IzkY4b4zUHUBFM1ojEYjZZYDcUW3bek/ufGionX9giIKDC5redH2IlGqcQQ==" }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -4945,16 +5080,18 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4964,15 +5101,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4982,15 +5120,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5000,18 +5139,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -5051,6 +5191,16 @@ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -5070,6 +5220,7 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/atomic-router/-/atomic-router-0.8.0.tgz", "integrity": "sha512-jUNmxqs4zKiTWnvcgNU7u51k+wS8XHYgy7YKTTwiuNB+PPRj+sRAjE+50nyExDygRS5A7yELhT14ziIICjQoqQ==", + "license": "MIT", "dependencies": { "path-to-regexp": "^6.2.0" }, @@ -5085,6 +5236,7 @@ "version": "0.8.5", "resolved": "https://registry.npmjs.org/atomic-router-react/-/atomic-router-react-0.8.5.tgz", "integrity": "sha512-XI+L5Kt+NSbVyZ8rc2M+9i4VslETv+ASNuR3wUm537p83mkXWVqZ37taNCsVDnX2D4vLGkfj8Fl6b/hw/tBqeQ==", + "license": "MIT", "dependencies": { "clsx": "^1.1.1" }, @@ -5098,11 +5250,21 @@ "react": "^17 || ^18" } }, + "node_modules/atomic-router/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "license": "MIT" + }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -5267,23 +5429,81 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, + "node_modules/bunshi": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/bunshi/-/bunshi-2.1.5.tgz", + "integrity": "sha512-zO+qxwd2aBV+XUIf7LjL1G3lx5CtvbtXZD+WMkM9KD+RN0iFtitDVX2QDu/wzdQIj8hyXJlGDfVEfeoqhAVEfA==", + "license": "MIT", "engines": { - "node": ">=8" - } + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "vue": ">=3" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5622,15 +5842,6 @@ "node": ">= 0.8" } }, - "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, - "engines": { - "node": ">= 6" - } - }, "node_modules/common-tags": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", @@ -5680,6 +5891,15 @@ "node": ">= 0.6" } }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, "node_modules/core-js-compat": { "version": "3.36.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", @@ -5766,6 +5986,15 @@ "node": ">=12 || >=16" } }, + "node_modules/css-in-js-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "license": "MIT", + "dependencies": { + "hyphenate-style-name": "^1.0.3" + } + }, "node_modules/css-mediaquery": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz", @@ -5822,9 +6051,10 @@ "dev": true }, "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -5880,6 +6110,60 @@ "node": ">=18" } }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", @@ -5908,6 +6192,15 @@ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", "dev": true }, + "node_modules/decode-uri-component": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", + "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, "node_modules/deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -5935,12 +6228,32 @@ "node": ">=0.10.0" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -6030,6 +6343,21 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -6037,9 +6365,9 @@ "dev": true }, "node_modules/effector": { - "version": "22.8.7", - "resolved": "https://registry.npmjs.org/effector/-/effector-22.8.7.tgz", - "integrity": "sha512-vCevjxmFwnZJuRGtqjwfi+sHtu+7gK3qdbv4fxi/AsMdDtoMeoz9C3/28pjNABviZeEARj6ZfAHbNAq5i9d7RQ==", + "version": "22.8.8", + "resolved": "https://registry.npmjs.org/effector/-/effector-22.8.8.tgz", + "integrity": "sha512-uqYEPt/jIZ3Y1WhpyED1XuXAJNsVM5TcWZvcyQhl6nYKRynklGiu+Fy/BnLQftmMcxZS478laAuExUPfuOGiOg==", "funding": [ { "type": "patreon", @@ -6050,6 +6378,7 @@ "url": "https://opencollective.com/effector" } ], + "license": "MIT", "engines": { "node": ">=11.0.0" } @@ -6058,6 +6387,7 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/effector-forms/-/effector-forms-1.3.4.tgz", "integrity": "sha512-m/Swvhf6eDyEgYINULCXLZf9uhMMicYQs4Te3bg5Hx2WdUeq5Cts18QwHU+YxoTTJh06rptWbHk0QHHmI4uPuA==", + "license": "ISC", "peerDependencies": { "effector": ">=22.0.0 <23.0.0", "effector-react": ">=22.2.0 <23.0.0" @@ -6067,6 +6397,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/effector-localstorage/-/effector-localstorage-1.0.0.tgz", "integrity": "sha512-SyJiKCHv05GPcWAC/lupQJWvp2EwY2QRfMuiy/JmuXxw++WUi5ozvxKrPT9ntRndn3AgD3S+LOPPwl7GWi/rzw==", + "license": "MIT", "peerDependencies": { "effector": ">=22.0.0" } @@ -6075,6 +6406,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/effector-mui-snacks/-/effector-mui-snacks-1.0.0.tgz", "integrity": "sha512-AY1ZlkV5/3yVoErF/8QDX95KjotygFWHh7GgxM5p5/cD/LsV/p7HYGy2rvTxqLrlKVxNtUGEvnzux3jwHYaNzg==", + "license": "ISC", "dependencies": { "classnames": "^2.3.2", "patronum": "^1.18.0" @@ -6101,6 +6433,7 @@ "url": "https://opencollective.com/effector" } ], + "license": "MIT", "dependencies": { "use-sync-external-store": "^1.0.0" }, @@ -6194,51 +6527,73 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/es-abstract": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", - "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", - "dev": true, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.1", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-array-concat": "^1.0.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.10" + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" }, "engines": { "node": ">= 0.4" @@ -6247,38 +6602,75 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -6806,6 +7198,91 @@ "ms": "^2.1.1" } }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz", + "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.7", + "enhanced-resolve": "^5.15.0", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3", + "stable-hash": "^0.0.4" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/enhanced-resolve": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", + "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-import-resolver-typescript/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/eslint-module-utils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -6921,51 +7398,38 @@ "node": ">=8" } }, - "node_modules/eslint-plugin-effector": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-effector/-/eslint-plugin-effector-0.11.0.tgz", - "integrity": "sha512-iujBwqh8z09lxrnTF3jAj2WHwxdKYWzf2DXn6ambdBjx3wgHgLt2vjpzctXxWR1+PPyoj3GyQYY7tsnc/RTNTw==", - "dev": true, - "dependencies": { - "prettier": "^2.3.2" - }, - "engines": { - "node": "^14 || ^15 || ^16 || ^17 || ^18 || ^19 || ^20" - }, - "peerDependencies": { - "effector": "*", - "eslint": "7 || 8" - } - }, "node_modules/eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/debug": { @@ -6989,6 +7453,40 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-import/node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-import/node_modules/is-core-module": { + "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": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.6.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz", @@ -7277,12 +7775,6 @@ "node": ">=4.0" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -7324,8 +7816,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.3.2", @@ -7355,6 +7846,11 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-shallow-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", + "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" + }, "node_modules/fast-uri": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", @@ -7370,6 +7866,12 @@ "node": ">= 4.9.1" } }, + "node_modules/fastest-stable-stringify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", + "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==", + "license": "MIT" + }, "node_modules/fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -7433,6 +7935,18 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -7474,12 +7988,19 @@ "dev": true }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.4.tgz", + "integrity": "sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/foreground-child": { @@ -7526,12 +8047,6 @@ "node": ">=14.14" } }, - "node_modules/fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -7553,20 +8068,27 @@ } }, "node_modules/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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -7612,15 +8134,25 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7632,6 +8164,20 @@ "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", "dev": true }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", @@ -7645,13 +8191,15 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -7660,6 +8208,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -7740,12 +8301,14 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -7790,12 +8353,13 @@ "dev": true }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7834,10 +8398,14 @@ } }, "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7851,22 +8419,27 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -7875,10 +8448,11 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7887,12 +8461,13 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -7901,6 +8476,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/headers-polyfill": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", @@ -7911,6 +8499,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz", "integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.6" } @@ -8016,6 +8605,12 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", + "license": "BSD-3-Clause" + }, "node_modules/i18next": { "version": "23.6.0", "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.6.0.tgz", @@ -8154,29 +8749,43 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "node_modules/inline-style-prefixer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", + "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", + "license": "MIT", + "dependencies": { + "css-in-js-utils": "^3.1.0" + } + }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8187,13 +8796,37 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8212,13 +8845,14 @@ } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", + "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8227,11 +8861,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-bun-module": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", + "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.6.3" + } + }, + "node_modules/is-bun-module/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/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -8250,13 +8908,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8274,6 +8952,22 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", @@ -8286,6 +8980,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -8298,17 +9011,12 @@ "node": ">=0.10.0" } }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -8316,6 +9024,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, "node_modules/is-node-process": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", @@ -8332,12 +9046,14 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8380,13 +9096,16 @@ "dev": true }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -8404,13 +9123,30 @@ "node": ">=0.10.0" } }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8429,12 +9165,14 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8444,12 +9182,15 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -8464,13 +9205,43 @@ "integrity": "sha512-vIZ7HTXAoRoIwYSsTnxb0sg9L6rth+JOulNcavsbskQkCIWoSM2cjFOWZs4wGziGZER+Xgs/HXiCQZgiL8ppxQ==", "dev": true }, - "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", + "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", "dev": true, + "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.11" + "call-bound": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8479,13 +9250,18 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8495,7 +9271,8 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", @@ -8743,17 +9520,24 @@ } }, "node_modules/joi": { - "version": "17.11.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", - "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", - "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9261,26 +10045,14 @@ "source-map-js": "^1.2.0" } }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, + "license": "MIT", "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" + "node": ">= 0.4" } }, "node_modules/mathml-tag-names": { @@ -9411,6 +10183,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9567,6 +10340,12 @@ "node": ">=8" } }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true + }, "node_modules/msw/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -9600,6 +10379,60 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/nano-css": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz", + "integrity": "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==", + "license": "Unlicense", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "css-tree": "^1.1.2", + "csstype": "^3.1.2", + "fastest-stable-stringify": "^2.0.2", + "inline-style-prefixer": "^7.0.1", + "rtl-css-js": "^1.16.1", + "stacktrace-js": "^2.0.2", + "stylis": "^4.3.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/nano-css/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/nano-css/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, + "node_modules/nano-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nano-css/node_modules/stylis": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.5.tgz", + "integrity": "sha512-K7npNOKGRYuhAFFzkzMGfxFDpN6gDwf8hcMiE+uveTVbBgm93HrNP3ZDUpKqzZ4pG7TP6fmb+EMAQPjq9FqqvA==", + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -9700,10 +10533,14 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9718,14 +10555,17 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -9750,14 +10590,16 @@ } }, "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -9767,15 +10609,18 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.hasown": { @@ -9793,14 +10638,16 @@ } }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -9856,6 +10703,24 @@ "integrity": "sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==", "dev": true }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -9984,9 +10849,13 @@ } }, "node_modules/path-to-regexp": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } }, "node_modules/path-type": { "version": "4.0.0", @@ -10015,6 +10884,7 @@ "version": "1.20.0", "resolved": "https://registry.npmjs.org/patronum/-/patronum-1.20.0.tgz", "integrity": "sha512-UsUR8nUbSPJ0kEQPNorZ/0+Rwlk+c45O4BfqlLHAdRQvx1C7ZSfC9txfPwJo+fajRtzVLebZm1m+67+Ke9SgdA==", + "license": "MIT", "peerDependencies": { "effector": "^22.1.2" } @@ -10049,15 +10919,6 @@ "node": ">=0.10" } }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/pkg-types": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.1.tgz", @@ -10113,6 +10974,16 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", @@ -10270,15 +11141,16 @@ } }, "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, + "license": "MIT", "bin": { - "prettier": "bin-prettier.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" @@ -10373,6 +11245,23 @@ "node": ">=6" } }, + "node_modules/query-string": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.1.1.tgz", + "integrity": "sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.4.1", + "filter-obj": "^5.1.0", + "split-on-first": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -10481,6 +11370,41 @@ "react-dom": ">=16.6.0" } }, + "node_modules/react-universal-interface": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", + "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==", + "peerDependencies": { + "react": "*", + "tslib": "*" + } + }, + "node_modules/react-use": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.6.0.tgz", + "integrity": "sha512-OmedEScUMKFfzn1Ir8dBxiLLSOzhKe/dPZwVxcujweSj45aNM7BEGPb9BEVIgVEqEXx6f3/TsXzwIktNgUR02g==", + "license": "Unlicense", + "dependencies": { + "@types/js-cookie": "^2.2.6", + "@xobotyi/scrollbar-width": "^1.9.5", + "copy-to-clipboard": "^3.3.1", + "fast-deep-equal": "^3.1.3", + "fast-shallow-equal": "^1.0.0", + "js-cookie": "^2.2.1", + "nano-css": "^5.6.2", + "react-universal-interface": "^0.6.2", + "resize-observer-polyfill": "^1.5.1", + "screenfull": "^5.1.0", + "set-harmonic-interval": "^1.0.1", + "throttle-debounce": "^3.0.1", + "ts-easing": "^0.2.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -10533,6 +11457,29 @@ "node": ">=8" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -10568,14 +11515,18 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -10646,6 +11597,12 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", @@ -10670,6 +11627,16 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/restore-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", @@ -10769,6 +11736,15 @@ "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", "dev": true }, + "node_modules/rtl-css-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -10795,17 +11771,20 @@ "node_modules/runtypes": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/runtypes/-/runtypes-6.7.0.tgz", - "integrity": "sha512-3TLdfFX8YHNFOhwHrSJza6uxVBmBrEjnNQlNXvXCdItS0Pdskfg5vVXUTWIN+Y23QR09jWpSl99UHkA83m4uWA==" + "integrity": "sha512-3TLdfFX8YHNFOhwHrSJza6uxVBmBrEjnNQlNXvXCdItS0Pdskfg5vVXUTWIN+Y23QR09jWpSl99UHkA83m4uWA==", + "license": "MIT" }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -10835,15 +11814,36 @@ } ] }, - "node_modules/safe-regex-test": { + "node_modules/safe-push-apply": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10875,6 +11875,18 @@ "loose-envify": "^1.1.0" } }, + "node_modules/screenfull": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", + "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -10893,6 +11905,64 @@ "randombytes": "^2.1.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-harmonic-interval": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", + "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==", + "license": "Unlicense", + "engines": { + "node": ">=6.9" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -10915,14 +11985,76 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10955,20 +12087,11 @@ "is-arrayish": "^0.3.1" } }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - }, - "node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true, - "engines": { - "node": ">=6" - } + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true }, "node_modules/slice-ansi": { "version": "5.0.0", @@ -11041,12 +12164,76 @@ "deprecated": "Please use @jridgewell/sourcemap-codec instead", "dev": true }, + "node_modules/split-on-first": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", + "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stable-hash": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", + "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", + "dev": true, + "license": "MIT" + }, + "node_modules/stack-generator": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz", + "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/stacktrace-gps": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz", + "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==", + "license": "MIT", + "dependencies": { + "source-map": "0.5.6", + "stackframe": "^1.3.4" + } + }, + "node_modules/stacktrace-gps/node_modules/source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stacktrace-js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz", + "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==", + "license": "MIT", + "dependencies": { + "error-stack-parser": "^2.0.6", + "stack-generator": "^2.0.5", + "stacktrace-gps": "^3.0.4" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -11186,14 +12373,19 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -11203,28 +12395,37 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11274,6 +12475,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -11972,6 +13174,15 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/tinybench": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", @@ -12016,6 +13227,12 @@ "node": ">=8.0" } }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "license": "MIT" + }, "node_modules/tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -12057,11 +13274,18 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-easing": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz", + "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==", + "license": "Unlicense" + }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -12074,6 +13298,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -12081,6 +13306,12 @@ "json5": "lib/cli.js" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -12115,29 +13346,32 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -12147,16 +13381,19 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -12166,14 +13403,21 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12342,15 +13586,19 @@ "dev": true }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13054,32 +14302,85 @@ } }, "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -13797,6 +15098,15 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } }, "dependencies": { @@ -13822,31 +15132,6 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, - "@babel/cli": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.23.0.tgz", - "integrity": "sha512-17E1oSkGk2IwNILM4jtfAvgjt+ohmpfBky8aLerUfYZhiPNg7ca+CRCxZn8QDxwNhV/upsc2VHBCqGFIR+iBfA==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.17", - "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", - "chokidar": "^3.4.0", - "commander": "^4.0.1", - "convert-source-map": "^2.0.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.2.0", - "make-dir": "^2.1.0", - "slash": "^2.0.0" - }, - "dependencies": { - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - } - } - }, "@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -14958,9 +16243,9 @@ "dev": true }, "@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", "requires": { "regenerator-runtime": "^0.14.0" }, @@ -15098,15 +16383,27 @@ } }, "@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", - "requires": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "requires": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" + }, + "dependencies": { + "@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" + }, + "@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" + } } }, "@emotion/hash": { @@ -15155,9 +16452,9 @@ } }, "@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" }, "@emotion/styled": { "version": "11.11.0", @@ -15184,9 +16481,9 @@ "requires": {} }, "@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==" }, "@emotion/weak-memoize": { "version": "0.3.1", @@ -15410,15 +16707,15 @@ "dev": true }, "@farfetched/core": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@farfetched/core/-/core-0.10.4.tgz", - "integrity": "sha512-sNhsuTL5/DPrpgp7JLN3rKJRxX6PHHG0h2Xlq4JjS2BzOGoJC/SB5iEr3kJyZLN4tjdXa2C0G/L7awf6sPh/4g==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@farfetched/core/-/core-0.10.6.tgz", + "integrity": "sha512-WSnQjftZ6ZfCFq+SOLvJpc52+xN4ND5azPPcuwOcygSZhKWs+P5wNH9WNpJ0KdP9ExOuol3JITze5LK2hLh+3g==", "requires": {} }, "@farfetched/runtypes": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@farfetched/runtypes/-/runtypes-0.10.4.tgz", - "integrity": "sha512-TRT6AfgFnwBQG3pjjMRC6UBlJ4DbNSvKILajINIJVhgt/9mmxlc8Mt+PObhpm9r0hhscPuLvsmBDKNIUk6UhnA==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@farfetched/runtypes/-/runtypes-0.10.6.tgz", + "integrity": "sha512-c7+WfJXi1eKy98B2ysaEgaDQMKIQB7dPoU21vB6fwDWD8hxU45z8/eUpRMA7DzRXZZWIytF8Rt0tMvMshL476g==", "requires": {} }, "@floating-ui/core": { @@ -15692,8 +16989,7 @@ "@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "@jridgewell/trace-mapping": { "version": "0.3.25", @@ -15741,9 +17037,9 @@ } }, "@mui/core-downloads-tracker": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.14.tgz", - "integrity": "sha512-Rw/xKiTOUgXD8hdKqj60aC6QcGprMipG7ne2giK6Mz7b4PlhL/xog9xLeclY3BxsRLkZQ05egFnIEY1CSibTbw==" + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.14.tgz", + "integrity": "sha512-sbjXW+BBSvmzn61XyTMun899E7nGPTXwqD9drm1jBUAvWEhJpPFIRxwQQiATWZnd9rvdxtnhhdsDxEGWI0jxqA==" }, "@mui/icons-material": { "version": "5.14.14", @@ -15769,103 +17065,108 @@ } }, "@mui/material": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.14.tgz", - "integrity": "sha512-cAmCwAHFQXxb44kWbVFkhKATN8tACgMsFwrXo8ro6WzYW73U/qsR5AcCiJIhCyYYg+gcftfkmNcpRaV3JjhHCg==", - "requires": { - "@babel/runtime": "^7.23.1", - "@mui/base": "5.0.0-beta.20", - "@mui/core-downloads-tracker": "^5.14.14", - "@mui/system": "^5.14.14", - "@mui/types": "^7.2.6", - "@mui/utils": "^5.14.13", - "@types/react-transition-group": "^4.4.7", - "clsx": "^2.0.0", - "csstype": "^3.1.2", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.14.tgz", + "integrity": "sha512-eSXQVCMKU2xc7EcTxe/X/rC9QsV2jUe8eLM3MUCPYbo6V52eCE436akRIvELq/AqZpxx2bwkq7HC0cRhLB+yaw==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/core-downloads-tracker": "^5.16.14", + "@mui/system": "^5.16.14", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.14", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", "prop-types": "^15.8.1", - "react-is": "^18.2.0", + "react-is": "^19.0.0", "react-transition-group": "^4.4.5" }, "dependencies": { - "@mui/base": { - "version": "5.0.0-beta.20", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.20.tgz", - "integrity": "sha512-CS2pUuqxST7ch9VNDCklRYDbJ3rru20Tx7na92QvVVKfu3RL4z/QLuVIc8jYGsdCnauMaeUSlFNLAJNb0yXe6w==", - "requires": { - "@babel/runtime": "^7.23.1", - "@floating-ui/react-dom": "^2.0.2", - "@mui/types": "^7.2.6", - "@mui/utils": "^5.14.13", - "@popperjs/core": "^2.11.8", - "clsx": "^2.0.0", - "prop-types": "^15.8.1" - } - }, "clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + }, + "react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==" } } }, "@mui/private-theming": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.14.tgz", - "integrity": "sha512-n77au3CQj9uu16hak2Y+rvbGSBaJKxziG/gEbOLVGrAuqZ+ycVSkorCfN6Y/4XgYOpG/xvmuiY3JwhAEOzY3iA==", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.14.tgz", + "integrity": "sha512-12t7NKzvYi819IO5IapW2BcR33wP/KAVrU8d7gLhGHoAmhDxyXlRoKiRij3TOD8+uzk0B6R9wHUNKi4baJcRNg==", "requires": { - "@babel/runtime": "^7.23.1", - "@mui/utils": "^5.14.13", + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.16.14", "prop-types": "^15.8.1" } }, "@mui/styled-engine": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.14.tgz", - "integrity": "sha512-sF3DS2PVG+cFWvkVHQQaGFpL1h6gSwOW3L91pdxPLQDHDZ5mZ/X0SlXU5XA+WjypoysG4urdAQC7CH/BRvUiqg==", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.14.tgz", + "integrity": "sha512-UAiMPZABZ7p8mUW4akDV6O7N3+4DatStpXMZwPlt+H/dA0lt67qawN021MNND+4QTpjaiMYxbhKZeQcyWCbuKw==", "requires": { - "@babel/runtime": "^7.23.1", - "@emotion/cache": "^11.11.0", - "csstype": "^3.1.2", + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.13.5", + "csstype": "^3.1.3", "prop-types": "^15.8.1" } }, "@mui/system": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.14.tgz", - "integrity": "sha512-y4InFmCgGGWXnz+iK4jRTWVikY0HgYnABjz4wgiUgEa2W1H8M4ow+27BegExUWPkj4TWthQ2qG9FOGSMtI+PKA==", - "requires": { - "@babel/runtime": "^7.23.1", - "@mui/private-theming": "^5.14.14", - "@mui/styled-engine": "^5.14.13", - "@mui/types": "^7.2.6", - "@mui/utils": "^5.14.13", - "clsx": "^2.0.0", - "csstype": "^3.1.2", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.14.tgz", + "integrity": "sha512-KBxMwCb8mSIABnKvoGbvM33XHyT+sN0BzEBG+rsSc0lLQGzs7127KWkCA6/H8h6LZ00XpBEME5MAj8mZLiQ1tw==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.16.14", + "@mui/styled-engine": "^5.16.14", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.14", + "clsx": "^2.1.0", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "dependencies": { "clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" } } }, "@mui/types": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.6.tgz", - "integrity": "sha512-7sjLQrUmBwufm/M7jw/quNiPK/oor2+pGUQP2CULRcFCArYTq78oJ3D5esTaL0UMkXKJvDqXn6Ike69yAOBQng==", + "version": "7.2.21", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.21.tgz", + "integrity": "sha512-6HstngiUxNqLU+/DPqlUJDIPbzUBxIVHb1MmXP0eTWDIROiCR2viugXpEif0PPe2mLqqakPzzRClWAnK+8UJww==", "requires": {} }, "@mui/utils": { - "version": "5.14.14", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.14.tgz", - "integrity": "sha512-3AKp8uksje5sRfVrtgG9Q/2TBsHWVBUtA0NaXliZqGcXo8J+A+Agp0qUW2rJ+ivgPWTCCubz9FZVT2IQZ3bGsw==", - "requires": { - "@babel/runtime": "^7.23.1", - "@types/prop-types": "^15.7.7", + "version": "5.16.14", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.14.tgz", + "integrity": "sha512-wn1QZkRzSmeXD1IguBVvJJHV3s6rxJrfb6YuC9Kk6Noh9f8Fb54nUs5JRkKm+BOerRhj5fLg05Dhx/H3Ofb8Mg==", + "requires": { + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", "prop-types": "^15.8.1", - "react-is": "^18.2.0" + "react-is": "^19.0.0" + }, + "dependencies": { + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + }, + "react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==" + } } }, "@mui/x-date-pickers": { @@ -15903,13 +17204,6 @@ } } }, - "@nicolo-ribaudo/chokidar-2": { - "version": "2.1.8-no-fsevents.3", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", - "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", - "dev": true, - "optional": true - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -15936,6 +17230,12 @@ "fastq": "^1.6.0" } }, + "@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true + }, "@open-draft/deferred-promise": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", @@ -15979,27 +17279,148 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, - "@rollup/plugin-babel": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.0.4.tgz", - "integrity": "sha512-YF7Y52kFdFT/xVSuVdjkV5ZdX/3YtmX0QulG+x0taQOtJdHYzVU61aSSkAgVJ7NOv6qPkIYiJSgSWWN/DM5sGw==", - "dev": true, + "@reatom/async": { + "version": "3.16.5", + "resolved": "https://registry.npmjs.org/@reatom/async/-/async-3.16.5.tgz", + "integrity": "sha512-vUEqXFg2PX8JsRJ8i7SB2RhXf/U3p/PwBOU2QVJNhX8DSamhyu+OIiKTxvOky2lvW3rIFOWy0ATpSLn6fh1pkw==", + "requires": { + "@reatom/core": "^3.5.0", + "@reatom/effects": "^3.10.0", + "@reatom/hooks": "^3.2.0", + "@reatom/primitives": "^3.5.0", + "@reatom/utils": "^3.11.0" + } + }, + "@reatom/core": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@reatom/core/-/core-3.9.3.tgz", + "integrity": "sha512-Ts0R41475+38HhTXFUWuYgxjE90jmZMMp5yvBONhGMYLyPIDtG/zJUmivSBwXtVOI5VYeiRW6T4VUkX7ZjnDGg==" + }, + "@reatom/devtools": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@reatom/devtools/-/devtools-0.9.2.tgz", + "integrity": "sha512-38BAClse/ENGe8S4fpQN8J8d0I47EWASUJopF9HLp9U8nFq9/Tox6pEv9rWmaqrLgy0euN8jZOQmJja+UYAz3A==", + "dev": true + }, + "@reatom/effects": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@reatom/effects/-/effects-3.11.1.tgz", + "integrity": "sha512-JhEB99+Wklfkg0kpV8sKvf1tP+16DaUXOaRYW1yxrHBleQ4WgOIO7j0hHqybmhMqJ/qS7Rcs3l8X0NBaH2bRJg==", + "requires": { + "@reatom/core": "^3.2.0", + "@reatom/utils": "^3.5.0" + } + }, + "@reatom/eslint-plugin": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@reatom/eslint-plugin/-/eslint-plugin-3.4.3.tgz", + "integrity": "sha512-2LelP4G1FXq+89pmWfKyNLV7GtxmmiHJfl2vac9oJU7lT+eqvmWi4Pd0duAJhWTLxvg9g5S1SLeGQ7tAw/gxeg==", + "dev": true + }, + "@reatom/framework": { + "version": "3.4.58", + "resolved": "https://registry.npmjs.org/@reatom/framework/-/framework-3.4.58.tgz", + "integrity": "sha512-iHKtf2N+57Uf6qQb/3rxij3pew/5LI7EliIuQTSgfmV15FxJktGDl9Vxj3KhEzW01XwnJBS7VRijuwS/Hz3Wvg==", + "requires": { + "@reatom/async": "^3.16.5", + "@reatom/core": "^3.9.3", + "@reatom/effects": "^3.11.1", + "@reatom/hooks": "^3.6.0", + "@reatom/lens": "^3.11.6", + "@reatom/logger": "^3.8.4", + "@reatom/primitives": "^3.7.3", + "@reatom/utils": "^3.11.2" + } + }, + "@reatom/hooks": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@reatom/hooks/-/hooks-3.6.0.tgz", + "integrity": "sha512-N3rqueSYvbQmuC2M2arF5Y7FHBK/rujK/gXXrVTTxXsetHMbwJAs7mxSB5a21s3eTHfCeOiuFCa8/qP7YL3ZVg==", + "requires": { + "@reatom/core": "^3.2.0", + "@reatom/effects": "^3.7.0", + "@reatom/utils": "^3.3.0" + } + }, + "@reatom/lens": { + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/@reatom/lens/-/lens-3.11.6.tgz", + "integrity": "sha512-kzsIq6dI5UKo4/aytBiIeSAXFVbWQ4ScrsNyJK7l47BE9COvetBbugwGhvHhLdLjrPoZMEadY09Ime8NglDt5A==", + "requires": { + "@reatom/core": "^3.4.0", + "@reatom/effects": "^3.2.0", + "@reatom/hooks": "^3.3.1", + "@reatom/primitives": "^3.6.0", + "@reatom/utils": "^3.1.0" + } + }, + "@reatom/logger": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/@reatom/logger/-/logger-3.8.4.tgz", + "integrity": "sha512-MOz8Td1eZV+kU4QpkZXAdO9qFtGjqpm40crIlMNweDtOH7GgUmV2oKgOXRORQzYbeGHVMlQHG4J5iPeEQdM7KA==", + "requires": { + "@reatom/core": "^3.8.1", + "@reatom/utils": "^3.9.0" + } + }, + "@reatom/npm-react": { + "version": "3.10.5", + "resolved": "https://registry.npmjs.org/@reatom/npm-react/-/npm-react-3.10.5.tgz", + "integrity": "sha512-TV86OP14sTY/JC9xSwTmYEmFu2J5mdKyezXKY2z6XuxXTGR+bNg37rxyZvPBwNigooAqlYfRrnxoPHpL8WP8fw==", + "requires": { + "@reatom/core": "^3.5.0", + "@reatom/effects": "^3.7.3", + "@reatom/lens": "^3.1.0", + "@reatom/utils": "^3.9.0", + "use-sync-external-store": "^1.2.0" + } + }, + "@reatom/persist": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@reatom/persist/-/persist-3.4.1.tgz", + "integrity": "sha512-LM3JriTJNSH1EluVcvW9ik7DK5oa0NeIgkz8rIGvVk/c9ZIqp0Olthc/WEB5qNNDdzZMrebGRFiHRM2iO5/T6A==", + "requires": { + "@reatom/core": "^3.3.0", + "@reatom/hooks": "^3.4.0", + "@reatom/lens": "^3.4.0", + "@reatom/utils": "^3.4.0" + } + }, + "@reatom/primitives": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@reatom/primitives/-/primitives-3.7.3.tgz", + "integrity": "sha512-HzG2aoGzE2W410ZSqnT8hd21Xd+bNMIkN03tq7dWgZ4OAZKawVnxdeB8bHu+oA5ppxICfrY0HtPUUeQTbvxfgQ==", "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@rollup/pluginutils": "^5.0.1" + "@reatom/core": "^3.1.1", + "@reatom/utils": "^3.1.1" } }, - "@rollup/pluginutils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", - "integrity": "sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==", + "@reatom/testing": { + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/@reatom/testing/-/testing-3.4.8.tgz", + "integrity": "sha512-9LtyEiQPgawYF6nQPXJB2LBx8ZWV92MJFL4PLLWW7L73a9Bbs4v3qnYlvT9dtLZGsxAEYHkxG2EAEg5Qrq8Ytw==", "dev": true, "requires": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^2.3.1" + "@reatom/core": "^3.5.0", + "@reatom/persist": "^3.3.0" + } + }, + "@reatom/url": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@reatom/url/-/url-3.8.0.tgz", + "integrity": "sha512-BlrF+xdGZ4x2D6LsGQRTG648TeQ+cNyulIh4SbROfDYPDBzgfHEvmAwT3qPWFoP8VR1CNhwujpnSOtUlYIi3hQ==", + "requires": { + "@reatom/core": "^3.5.0", + "@reatom/effects": "^3.7.0", + "@reatom/hooks": "^3.4.0", + "@reatom/utils": "^3.4.0" } }, + "@reatom/utils": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/@reatom/utils/-/utils-3.11.2.tgz", + "integrity": "sha512-4xeSI8mQ3OEg0cUFYuQu3EMe4NJm2NKggImIV3Lm1ApIPue5F9rJ0geQ30BEAixDiMb8XUuEL5Hlzy1uuOqkQQ==" + }, "@rollup/rollup-android-arm-eabi": { "version": "4.18.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", @@ -16112,10 +17533,16 @@ "dev": true, "optional": true }, + "@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, "@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", "requires": { "@hapi/hoek": "^9.0.0" } @@ -16396,6 +17823,11 @@ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "@types/js-cookie": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", + "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==" + }, "@types/json-schema": { "version": "7.0.14", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", @@ -16432,9 +17864,9 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "@types/prop-types": { - "version": "15.7.9", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.9.tgz", - "integrity": "sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==" + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" }, "@types/react": { "version": "18.2.31", @@ -16456,12 +17888,10 @@ } }, "@types/react-transition-group": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.8.tgz", - "integrity": "sha512-QmQ22q+Pb+HQSn04NL3HtrqHwYMf4h3QKArOy5F8U5nEVMaihBs3SR10WiOM1iwPz5jIo8x/u11al+iEGZZrvg==", - "requires": { - "@types/react": "*" - } + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "requires": {} }, "@types/resolve": { "version": "1.17.1", @@ -16852,11 +18282,16 @@ } }, "@withease/web-api": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@withease/web-api/-/web-api-1.0.1.tgz", - "integrity": "sha512-KC+6ueVd1rEpLvMN7uXHa7E5TKdv7MxIhEAAs8tjAgmKxkUgranpsrjU2ZlwHGimuc98Z428/n+zgldZE3nIMg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@withease/web-api/-/web-api-1.3.0.tgz", + "integrity": "sha512-ULQu1yOoKDom7kGNg2KHeb3OJm09CbNRBZfJ/H9Mpuwia7Cydw8o0vHQEtDFyPmwYm7OIhCNEw/ILZUHzNJCQQ==", "requires": {} }, + "@xobotyi/scrollbar-width": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", + "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==" + }, "acorn": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", @@ -16964,25 +18399,26 @@ "integrity": "sha512-fExL2kFDC1Q2DUOx3whE/9KoN66IzkY4b4zUHUBFM1ojEYjZZYDcUW3bek/ufGionX9giIKDC5redH2IlGqcQQ==" }, "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" } }, "array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" } }, @@ -16993,55 +18429,56 @@ "dev": true }, "array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" } }, "array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" } }, "array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" } }, "arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, "requires": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" } }, "assertion-error": { @@ -17069,6 +18506,12 @@ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, + "async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -17087,6 +18530,13 @@ "integrity": "sha512-jUNmxqs4zKiTWnvcgNU7u51k+wS8XHYgy7YKTTwiuNB+PPRj+sRAjE+50nyExDygRS5A7yELhT14ziIICjQoqQ==", "requires": { "path-to-regexp": "^6.2.0" + }, + "dependencies": { + "path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" + } } }, "atomic-router-react": { @@ -17098,10 +18548,13 @@ } }, "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "requires": { + "possible-typed-array-names": "^1.0.0" + } }, "axe-core": { "version": "4.5.2", @@ -17212,6 +18665,12 @@ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true }, + "bunshi": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/bunshi/-/bunshi-2.1.5.tgz", + "integrity": "sha512-zO+qxwd2aBV+XUIf7LjL1G3lx5CtvbtXZD+WMkM9KD+RN0iFtitDVX2QDu/wzdQIj8hyXJlGDfVEfeoqhAVEfA==", + "requires": {} + }, "cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -17219,13 +18678,35 @@ "dev": true }, "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + } + }, + "call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, + "call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" } }, "callsites": { @@ -17468,12 +18949,6 @@ "delayed-stream": "~1.0.0" } }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, "common-tags": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", @@ -17517,6 +18992,14 @@ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "dev": true }, + "copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "requires": { + "toggle-selection": "^1.0.6" + } + }, "core-js-compat": { "version": "3.36.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", @@ -17582,6 +19065,14 @@ "integrity": "sha512-c+N0v6wbKVxTu5gOBBFkr9BEdBWaqqjQeiJ8QvSRIJOf+UxlJh930m8e6/WNeODIK0mYLFkoONrnj16i2EcvfQ==", "dev": true }, + "css-in-js-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "requires": { + "hyphenate-style-name": "^1.0.3" + } + }, "css-mediaquery": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz", @@ -17628,9 +19119,9 @@ } }, "csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "damerau-levenshtein": { "version": "1.0.8", @@ -17676,6 +19167,39 @@ } } }, + "data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + } + }, + "data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + } + }, + "data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, "dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", @@ -17696,6 +19220,11 @@ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", "dev": true }, + "decode-uri-component": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", + "integrity": "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==" + }, "deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -17717,12 +19246,24 @@ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "requires": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } @@ -17785,6 +19326,17 @@ "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", "dev": true }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -17792,9 +19344,9 @@ "dev": true }, "effector": { - "version": "22.8.7", - "resolved": "https://registry.npmjs.org/effector/-/effector-22.8.7.tgz", - "integrity": "sha512-vCevjxmFwnZJuRGtqjwfi+sHtu+7gK3qdbv4fxi/AsMdDtoMeoz9C3/28pjNABviZeEARj6ZfAHbNAq5i9d7RQ==" + "version": "22.8.8", + "resolved": "https://registry.npmjs.org/effector/-/effector-22.8.8.tgz", + "integrity": "sha512-uqYEPt/jIZ3Y1WhpyED1XuXAJNsVM5TcWZvcyQhl6nYKRynklGiu+Fy/BnLQftmMcxZS478laAuExUPfuOGiOg==" }, "effector-forms": { "version": "1.3.4", @@ -17886,82 +19438,124 @@ "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", - "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", - "dev": true, + "error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", "requires": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.1", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "stackframe": "^1.3.4" + } + }, + "es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-array-concat": "^1.0.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.10" + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" + } + }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0" } }, "es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" } }, "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" } }, "esbuild": { @@ -18320,6 +19914,55 @@ } } }, + "eslint-import-resolver-typescript": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz", + "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==", + "dev": true, + "requires": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.7", + "enhanced-resolve": "^5.15.0", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3", + "stable-hash": "^0.0.4" + }, + "dependencies": { + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + }, + "enhanced-resolve": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", + "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + } + } + }, "eslint-module-utils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", @@ -18404,38 +20047,31 @@ } } }, - "eslint-plugin-effector": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-effector/-/eslint-plugin-effector-0.11.0.tgz", - "integrity": "sha512-iujBwqh8z09lxrnTF3jAj2WHwxdKYWzf2DXn6ambdBjx3wgHgLt2vjpzctXxWR1+PPyoj3GyQYY7tsnc/RTNTw==", - "dev": true, - "requires": { - "prettier": "^2.3.2" - } - }, "eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, "requires": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" }, "dependencies": { "debug": { @@ -18455,6 +20091,24 @@ "requires": { "esutils": "^2.0.2" } + }, + "eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "requires": { + "debug": "^3.2.7" + } + }, + "is-core-module": { + "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": { + "hasown": "^2.0.2" + } } } }, @@ -18593,12 +20247,6 @@ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -18631,8 +20279,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.3.2", @@ -18659,6 +20306,11 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "fast-shallow-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", + "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" + }, "fast-uri": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", @@ -18671,6 +20323,11 @@ "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true }, + "fastest-stable-stringify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", + "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==" + }, "fastq": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", @@ -18727,6 +20384,11 @@ "to-regex-range": "^5.0.1" } }, + "filter-obj": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-5.1.0.tgz", + "integrity": "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==" + }, "find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -18759,12 +20421,12 @@ "dev": true }, "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.4.tgz", + "integrity": "sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==", "dev": true, "requires": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" } }, "foreground-child": { @@ -18799,12 +20461,6 @@ "universalify": "^2.0.0" } }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -18819,20 +20475,22 @@ "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==" }, "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" } }, "functions-have-names": { @@ -18860,15 +20518,21 @@ "dev": true }, "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "function-bind": "^1.1.2", + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" } }, "get-own-enumerable-property-symbols": { @@ -18877,6 +20541,16 @@ "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", "dev": true }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + } + }, "get-stream": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", @@ -18884,13 +20558,23 @@ "dev": true }, "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + } + }, + "get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" } }, "glob": { @@ -18954,12 +20638,13 @@ "dev": true }, "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "requires": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" } }, "globby": { @@ -18991,13 +20676,10 @@ "dev": true }, "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true }, "graceful-fs": { "version": "4.2.11", @@ -19026,9 +20708,9 @@ } }, "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true }, "has-flag": { @@ -19037,33 +20719,45 @@ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "requires": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" } }, "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.0" + } }, "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true }, "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.3" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "function-bind": "^1.1.2" } }, "headers-polyfill": { @@ -19156,6 +20850,11 @@ "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true }, + "hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==" + }, "i18next": { "version": "23.6.0", "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.6.0.tgz", @@ -19257,26 +20956,34 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "inline-style-prefixer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", + "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", + "requires": { + "css-in-js-utils": "^3.1.0" + } + }, "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" } }, "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" } }, "is-arrayish": { @@ -19284,13 +20991,26 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, + "is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "requires": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + } + }, "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "requires": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" } }, "is-binary-path": { @@ -19303,13 +21023,30 @@ } }, "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", + "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + } + }, + "is-bun-module": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", + "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", + "dev": true, + "requires": { + "semver": "^7.6.3" + }, + "dependencies": { + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true + } } }, "is-callable": { @@ -19326,13 +21063,25 @@ "has": "^1.0.3" } }, + "is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + } + }, "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" } }, "is-extglob": { @@ -19341,12 +21090,33 @@ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, + "is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "requires": { + "call-bound": "^1.0.3" + } + }, "is-fullwidth-code-point": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true }, + "is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "requires": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + } + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -19356,18 +21126,18 @@ "is-extglob": "^2.1.1" } }, + "is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true + }, "is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", "dev": true }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true - }, "is-node-process": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", @@ -19381,12 +21151,13 @@ "dev": true }, "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-obj": { @@ -19414,13 +21185,15 @@ "dev": true }, "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" } }, "is-regexp": { @@ -19429,13 +21202,19 @@ "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", "dev": true }, + "is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true + }, "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" } }, "is-stream": { @@ -19445,21 +21224,24 @@ "dev": true }, "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" } }, "is-there": { @@ -19469,21 +21251,37 @@ "dev": true }, "is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "requires": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.16" } }, + "is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true + }, "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", + "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", + "dev": true, + "requires": { + "call-bound": "^1.0.2" + } + }, + "is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" } }, "isarray": { @@ -19670,17 +21468,22 @@ } }, "joi": { - "version": "17.11.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", - "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", "requires": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, + "js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -20073,23 +21876,11 @@ "source-map-js": "^1.2.0" } }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true }, "mathml-tag-names": { "version": "2.1.3", @@ -20287,6 +22078,12 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -20310,6 +22107,47 @@ "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", "dev": true }, + "nano-css": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz", + "integrity": "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==", + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "css-tree": "^1.1.2", + "csstype": "^3.1.2", + "fastest-stable-stringify": "^2.0.2", + "inline-style-prefixer": "^7.0.1", + "rtl-css-js": "^1.16.1", + "stacktrace-js": "^2.0.2", + "stylis": "^4.3.0" + }, + "dependencies": { + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "stylis": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.5.tgz", + "integrity": "sha512-K7npNOKGRYuhAFFzkzMGfxFDpN6gDwf8hcMiE+uveTVbBgm93HrNP3ZDUpKqzZ4pG7TP6fmb+EMAQPjq9FqqvA==" + } + } + }, "nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -20371,9 +22209,9 @@ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true }, "object-keys": { @@ -20383,14 +22221,16 @@ "dev": true }, "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, @@ -20406,26 +22246,26 @@ } }, "object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" } }, "object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" } }, "object.hasown": { @@ -20440,14 +22280,15 @@ } }, "object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "once": { @@ -20488,6 +22329,17 @@ "integrity": "sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==", "dev": true }, + "own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + } + }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -20576,9 +22428,9 @@ } }, "path-to-regexp": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==" }, "path-type": { "version": "4.0.0", @@ -20621,12 +22473,6 @@ "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, "pkg-types": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.1.tgz", @@ -20663,6 +22509,12 @@ "integrity": "sha512-+hkOycxPiV534c4HhpfX6yrlawqVUzITRKwHAmYfmsVreltEl6fAZJ3DPfLMOODw0H3s1Itd6MDCWmP1fl/QvQ==", "dev": true }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true + }, "postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", @@ -20753,9 +22605,9 @@ "dev": true }, "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true }, "pretty-bytes": { @@ -20833,6 +22685,16 @@ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true }, + "query-string": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-9.1.1.tgz", + "integrity": "sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==", + "requires": { + "decode-uri-component": "^0.4.1", + "filter-obj": "^5.1.0", + "split-on-first": "^3.0.0" + } + }, "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -20902,6 +22764,33 @@ "prop-types": "^15.6.2" } }, + "react-universal-interface": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", + "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==", + "requires": {} + }, + "react-use": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.6.0.tgz", + "integrity": "sha512-OmedEScUMKFfzn1Ir8dBxiLLSOzhKe/dPZwVxcujweSj45aNM7BEGPb9BEVIgVEqEXx6f3/TsXzwIktNgUR02g==", + "requires": { + "@types/js-cookie": "^2.2.6", + "@xobotyi/scrollbar-width": "^1.9.5", + "copy-to-clipboard": "^3.3.1", + "fast-deep-equal": "^3.1.3", + "fast-shallow-equal": "^1.0.0", + "js-cookie": "^2.2.1", + "nano-css": "^5.6.2", + "react-universal-interface": "^0.6.2", + "resize-observer-polyfill": "^1.5.1", + "screenfull": "^5.1.0", + "set-harmonic-interval": "^1.0.1", + "throttle-debounce": "^3.0.1", + "ts-easing": "^0.2.0", + "tslib": "^2.1.0" + } + }, "readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -20950,6 +22839,22 @@ "strip-indent": "^3.0.0" } }, + "reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "requires": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + } + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -20982,14 +22887,17 @@ } }, "regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" } }, "regexpu-core": { @@ -21041,6 +22949,11 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, "resolve": { "version": "1.22.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", @@ -21056,6 +22969,12 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true + }, "restore-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", @@ -21125,6 +23044,14 @@ "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", "dev": true }, + "rtl-css-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -21140,14 +23067,15 @@ "integrity": "sha512-3TLdfFX8YHNFOhwHrSJza6uxVBmBrEjnNQlNXvXCdItS0Pdskfg5vVXUTWIN+Y23QR09jWpSl99UHkA83m4uWA==" }, "safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, @@ -21157,15 +23085,25 @@ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, - "safe-regex-test": { + "safe-push-apply": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + } + }, + "safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" } }, "safer-buffer": { @@ -21191,6 +23129,11 @@ "loose-envify": "^1.1.0" } }, + "screenfull": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", + "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==" + }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -21206,6 +23149,48 @@ "randombytes": "^2.1.0" } }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + } + }, + "set-harmonic-interval": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", + "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==" + }, + "set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -21222,14 +23207,51 @@ "dev": true }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" } }, "siginfo": { @@ -21261,12 +23283,6 @@ } } }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, "slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", @@ -21320,12 +23336,62 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "dev": true }, + "split-on-first": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-3.0.0.tgz", + "integrity": "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==" + }, + "stable-hash": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", + "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", + "dev": true + }, + "stack-generator": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz", + "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==", + "requires": { + "stackframe": "^1.3.4" + } + }, "stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true }, + "stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "stacktrace-gps": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz", + "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==", + "requires": { + "source-map": "0.5.6", + "stackframe": "^1.3.4" + }, + "dependencies": { + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==" + } + } + }, + "stacktrace-js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz", + "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==", + "requires": { + "error-stack-parser": "^2.0.6", + "stack-generator": "^2.0.5", + "stacktrace-gps": "^3.0.4" + } + }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -21437,36 +23503,41 @@ } }, "string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" } }, "string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "stringify-object": { @@ -22012,6 +24083,11 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==" + }, "tinybench": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", @@ -22044,6 +24120,11 @@ "is-number": "^7.0.0" } }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, "tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -22076,10 +24157,15 @@ "dev": true, "requires": {} }, + "ts-easing": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz", + "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==" + }, "tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "requires": { "@types/json5": "^0.0.29", @@ -22099,6 +24185,11 @@ } } }, + "tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -22121,50 +24212,56 @@ "dev": true }, "typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" } }, "typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" } }, "typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" } }, "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" } }, "typed-css-modules": { @@ -22283,15 +24380,15 @@ "dev": true }, "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" } }, "undici-types": { @@ -22686,29 +24783,63 @@ } }, "which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "requires": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + } + }, + "which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + } + }, + "which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" } }, "which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" } }, "why-is-node-running": { @@ -23268,6 +25399,11 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "zod": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==" } } } diff --git a/package.json b/package.json index 7b03c9eb..b4b429ff 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test:e2e:ui": "npx playwright test --ui", "lint": "eslint --ext .tsx,.ts src", "lint:fix": "eslint --ext .tsx,.ts src --fix", - "prettier": "prettier --write --config ./.prettierrc src", + "format": "prettier --write --config ./.prettierrc src", "prepare": "husky install", "gen:css-types": "tcm src" }, @@ -25,11 +25,16 @@ "@fontsource/roboto": "^5.0.8", "@mui/icons-material": "^5.14.14", "@mui/lab": "^5.0.0-alpha.108", - "@mui/material": "^5.14.14", + "@mui/material": "^5.16.14", "@mui/x-date-pickers": "^6.16.2", + "@reatom/framework": "^3.4.58", + "@reatom/npm-react": "^3.10.5", + "@reatom/persist": "^3.4.1", + "@reatom/url": "^3.8.0", "@withease/web-api": "^1.0.1", "atomic-router": "^0.8.0", "atomic-router-react": "^0.8.5", + "bunshi": "^2.1.5", "classnames": "^2.3.1", "compose-function": "^3.0.3", "dayjs": "^1.11.10", @@ -44,18 +49,21 @@ "i18next-http-backend": "^2.2.2", "joi": "^17.11.0", "ky": "^1.1.0", - "patronum": "^1.20.0", + "path-to-regexp": "^8.2.0", + "query-string": "^9.1.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-i18next": "^13.3.1", - "runtypes": "^6.7.0" + "react-use": "^17.6.0", + "runtypes": "^6.7.0", + "zod": "^3.24.1" }, "devDependencies": { - "@babel/cli": "^7.23.0", - "@babel/core": "^7.23.2", "@faker-js/faker": "^8.4.1", "@playwright/test": "^1.40.1", - "@rollup/plugin-babel": "^6.0.4", + "@reatom/devtools": "^0.9.2", + "@reatom/eslint-plugin": "^3.4.3", + "@reatom/testing": "^3.4.8", "@testing-library/jest-dom": "^6.4.6", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.5.2", @@ -71,8 +79,8 @@ "eslint": "^8.51.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-boundaries": "^3.4.0", - "eslint-plugin-effector": "^0.11.0", "eslint-plugin-import": "^2.28.1", "eslint-plugin-sonarjs": "^0.21.0", "husky": "^8.0.3", @@ -80,6 +88,7 @@ "lint-staged": "^15.0.2", "mock-match-media": "^0.4.3", "msw": "^2.3.1", + "prettier": "^3.4.2", "stylelint": "^16.9.0", "stylelint-color-format": "^1.1.0", "stylelint-config-clean-order": "^6.1.0", diff --git a/src/app/providers/index.ts b/src/app/providers/index.ts index 7c73ea15..ef7dfe84 100644 --- a/src/app/providers/index.ts +++ b/src/app/providers/index.ts @@ -5,6 +5,7 @@ import { withGlobalStyles } from './withGlobalStyles'; import { withI18n } from './withI18n'; import { withNotifications } from './withNotifications'; import { withRouter } from './withRouter'; +import { withStore } from './withStore'; import { withStrictMode } from './withStrictMode'; export const withProviders = compose( @@ -13,5 +14,6 @@ export const withProviders = compose( withRouter, withGlobalStyles, withErrorBoundary, - withNotifications + withNotifications, + withStore ); diff --git a/src/app/providers/withStore.tsx b/src/app/providers/withStore.tsx new file mode 100644 index 00000000..40e7a256 --- /dev/null +++ b/src/app/providers/withStore.tsx @@ -0,0 +1,14 @@ +import { reatomContext } from '@reatom/npm-react'; +import { ComponentType } from 'react'; + +import { ctx } from '@/shared/configs'; + +export const withStore = + (Component: ComponentType): ComponentType => + () => { + return ( + + + + ); + }; diff --git a/src/entities/activities/index.ts b/src/entities/activities/index.ts index 1f437247..dfb222dc 100644 --- a/src/entities/activities/index.ts +++ b/src/entities/activities/index.ts @@ -1,3 +1,3 @@ export * from './ui'; -export * from './model'; +export * from './models'; export * from './lib'; diff --git a/src/entities/activities/lib/index.ts b/src/entities/activities/lib/index.ts index ac7f95af..75af9b34 100644 --- a/src/entities/activities/lib/index.ts +++ b/src/entities/activities/lib/index.ts @@ -1,2 +1,3 @@ export * from './use-activity-actions'; export * from './use-activity-spheres'; +export * from './use-activities'; diff --git a/src/entities/activities/lib/use-activities.ts b/src/entities/activities/lib/use-activities.ts new file mode 100644 index 00000000..98f0eb56 --- /dev/null +++ b/src/entities/activities/lib/use-activities.ts @@ -0,0 +1,7 @@ +import { useMolecule } from 'bunshi/react'; + +import { activititesModel } from '../models'; + +export const useActivities = () => { + return useMolecule(activititesModel.Molecule); +}; diff --git a/src/entities/activities/lib/use-activity-actions.ts b/src/entities/activities/lib/use-activity-actions.ts index 03b41c40..8598370e 100644 --- a/src/entities/activities/lib/use-activity-actions.ts +++ b/src/entities/activities/lib/use-activity-actions.ts @@ -1,7 +1,7 @@ -import { useUnit } from 'effector-react'; +import { useMolecule } from 'bunshi/react'; -import { activityActionsModel } from '../model'; +import { activityActionsModel } from '../models'; export const useActivityActions = () => { - return useUnit(activityActionsModel.query); + return useMolecule(activityActionsModel.Molecule); }; diff --git a/src/entities/activities/lib/use-activity-spheres.ts b/src/entities/activities/lib/use-activity-spheres.ts index 8f3fa220..645bfe6e 100644 --- a/src/entities/activities/lib/use-activity-spheres.ts +++ b/src/entities/activities/lib/use-activity-spheres.ts @@ -1,10 +1,7 @@ -import { useUnit } from 'effector-react'; +import { useMolecule } from 'bunshi/react'; -import { activitySpheresModel } from '../model'; +import { activitySpheresModel } from '../models'; -/** - * @deprecated - */ export const useActivitySpheres = () => { - return useUnit(activitySpheresModel.query); + return useMolecule(activitySpheresModel.Molecule); }; diff --git a/src/entities/activities/model/activities-in-room.ts b/src/entities/activities/model/activities-in-room.ts deleted file mode 100644 index fe04d6ff..00000000 --- a/src/entities/activities/model/activities-in-room.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { cache, createQuery, keepFresh } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createDomain } from 'effector'; -import { interval } from 'patronum'; - -import { - Activity, - activity, - GetActivitiesInRoomParams, - activitiesApi -} from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { - StandardResponse, - getStandardResponse, - PaginationResponse, - getPaginationResponse -} from '@/shared/types'; - -const activitiesDomain = createDomain(); -const handlerFx = activitiesDomain.effect< - GetActivitiesInRoomParams, - StandardResponse> ->(activitiesApi.getAll); - -export const query = createQuery< - GetActivitiesInRoomParams, - StandardResponse>, - Error, - StandardResponse>, - PaginationResponse ->({ - initialData: { items: [], totalCount: 0, limit: 50, }, - effect: handlerFx, - contract: runtypeContract( - getStandardResponse(getPaginationResponse(activity)) - ), - mapData: extractData, -}); - -export const $hasItems = query.$data.map((data) => !!data.totalCount); -export const $pageCount = query.$data.map((data) => - Math.ceil(data.totalCount / data.limit) -); - -cache(query); - -keepFresh(query, { - triggers: [interval({ timeout: 5000, })], -}); diff --git a/src/entities/activities/model/activity-actions.ts b/src/entities/activities/model/activity-actions.ts deleted file mode 100644 index 0510beb4..00000000 --- a/src/entities/activities/model/activity-actions.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { cache, createQuery } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createDomain } from 'effector'; -import { Array } from 'runtypes'; - -import { activitiesApi, ActivityAction, activityAction } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { getStandardResponse, StandardResponse } from '@/shared/types'; - -const activityActions = createDomain(); - -const handlerFx = activityActions.effect(activitiesApi.getActions); - -export const query = createQuery< - void, - StandardResponse, - Error, - StandardResponse, - ActivityAction[] ->({ - initialData: [], - effect: handlerFx, - contract: runtypeContract(getStandardResponse(Array(activityAction))), - mapData: extractData, -}); - -cache(query); diff --git a/src/entities/activities/model/activity-spheres.ts b/src/entities/activities/model/activity-spheres.ts deleted file mode 100644 index caab5d3e..00000000 --- a/src/entities/activities/model/activity-spheres.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { cache, createQuery } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createDomain } from 'effector'; -import { Array } from 'runtypes'; - -import { activitiesApi, ActivitySphere, activitySphere } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { getStandardResponse, StandardResponse } from '@/shared/types'; - -const activitySpheres = createDomain(); - -const handlerFx = activitySpheres.effect(activitiesApi.getSpheres); - -export const query = createQuery< - void, - StandardResponse, - Error, - StandardResponse, - ActivitySphere[] ->({ - initialData: [], - effect: handlerFx, - contract: runtypeContract(getStandardResponse(Array(activitySphere))), - mapData: extractData, -}); - -cache(query); diff --git a/src/entities/activities/model/index.ts b/src/entities/activities/model/index.ts deleted file mode 100644 index f0866299..00000000 --- a/src/entities/activities/model/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * as activitiesInRoomModel from './activities-in-room'; -export * as activityActionsModel from './activity-actions'; -export * as activitySpheresModel from './activity-spheres'; diff --git a/src/entities/activities/models/actions/index.ts b/src/entities/activities/models/actions/index.ts new file mode 100644 index 00000000..24c13f15 --- /dev/null +++ b/src/entities/activities/models/actions/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as activityActionsModel from './model'; diff --git a/src/entities/activities/models/actions/model.spec.ts b/src/entities/activities/models/actions/model.spec.ts new file mode 100644 index 00000000..734a83e4 --- /dev/null +++ b/src/entities/activities/models/actions/model.spec.ts @@ -0,0 +1,42 @@ +import { getDefaultInjector } from 'bunshi'; +import { beforeEach, describe, expect, test } from 'vitest'; + +import { TestCtx, actions, createTestCtx, waitNextTick } from '~/test-utils'; + +import { Molecule } from './model'; +import { ActivityActionsModel } from './types'; + +describe('entities/activitites/models/actions/model.ts', () => { + let ctx: TestCtx; + let model: ActivityActionsModel; + + const createModel = () => { + model = getDefaultInjector().get(Molecule); + }; + + beforeEach(() => { + ctx = createTestCtx(); + }); + + test('should create signleton model', () => { + createModel(); + + const oldModel = model; + + createModel(); + + expect(model).toBe(oldModel); + }); + + test('should load all actions', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.actionsAtom); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual(actions); + + track.unsubscribe(); + }); +}); diff --git a/src/entities/activities/models/actions/model.ts b/src/entities/activities/models/actions/model.ts new file mode 100644 index 00000000..68e076f7 --- /dev/null +++ b/src/entities/activities/models/actions/model.ts @@ -0,0 +1,55 @@ +import { + atom, + reatomResource, + withCache, + withDataAtom, + withErrorAtom, + withRetry +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { molecule } from 'bunshi'; + +import { activitiesApi } from '@/shared/api'; +import { constructName, mapStandardResponse } from '@/shared/lib'; + +import { + ActivityActions, + ActivityActionsModel, + activityActionsResponseSchema +} from './types'; + + +const modelName = constructName('activitites', 'actions'); + +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(createMemStorage({ name: modelName, })); + +export const Molecule = molecule((): ActivityActionsModel => { + const fetch = reatomResource( + async (ctx) => { + return ctx.schedule(() => + activitiesApi + .getActions({ signal: ctx.controller.signal, }) + .then(activityActionsResponseSchema.parseAsync) + ); + }, + constructName(modelName, 'fetch') + ).pipe( + withDataAtom([] as ActivityActions, mapStandardResponse), + withCache({ withPersist, }), + withRetry(), + withErrorAtom(undefined, { initState: null, }) + ); + + const { errorAtom, dataAtom: actionsAtom, } = fetch; + const pendingAtom = atom( + (ctx) => !!ctx.spy(fetch.pendingAtom), + constructName(modelName, 'pendingAtom') + ); + + return { + actionsAtom, + errorAtom, + pendingAtom, + }; +}); diff --git a/src/entities/activities/models/actions/types.ts b/src/entities/activities/models/actions/types.ts new file mode 100644 index 00000000..cf22652e --- /dev/null +++ b/src/entities/activities/models/actions/types.ts @@ -0,0 +1,27 @@ +import { Atom } from '@reatom/framework'; +import zod from 'zod'; + +import { createStandardResponseSchema } from '@/shared/lib'; + +export const activityActionSchema = zod + .object({ + id: zod.number(), + name: zod.string(), + }) + .readonly(); +export const activityActionsSchema = zod.array(activityActionSchema); + +export const activityActionsResponseSchema = createStandardResponseSchema( + activityActionsSchema +); + +export interface ActivityAction + extends zod.infer {} +export type ActivityActionId = ActivityAction['id']; +export type ActivityActions = ActivityAction[]; + +export interface ActivityActionsModel { + readonly actionsAtom: Atom; + readonly errorAtom: Atom; + readonly pendingAtom: Atom; +} diff --git a/src/entities/activities/models/activities/index.ts b/src/entities/activities/models/activities/index.ts new file mode 100644 index 00000000..98fdb41d --- /dev/null +++ b/src/entities/activities/models/activities/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as activititesModel from './model'; diff --git a/src/entities/activities/models/activities/model.spec.ts b/src/entities/activities/models/activities/model.spec.ts new file mode 100644 index 00000000..b69be25f --- /dev/null +++ b/src/entities/activities/models/activities/model.spec.ts @@ -0,0 +1,114 @@ +import { take, takeNested } from '@reatom/framework'; +import { getDefaultInjector } from 'bunshi'; +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; + +import { + TestCtx, + createTestCtx, + defaultRoom, + activities, + actions, + rooms +} from '~/test-utils'; + +// eslint-disable-next-line no-restricted-imports +import { roomModel } from '@/entities/rooms/@x/activities'; + +import { Molecule } from './model'; +import { ActivitiesModel } from './types'; + +describe('entities/activitites/models/activities/model.ts', () => { + const defaultRoomId = defaultRoom.id; + + let ctx: TestCtx; + let model: ActivitiesModel; + + const createModel = (roomId = defaultRoomId) => { + model = getDefaultInjector().get(Molecule, [roomModel.Scope, roomId]); + }; + + beforeEach(() => { + ctx = createTestCtx(); + + vi.useFakeTimers(); + }); + + afterEach(async () => { + await vi.runOnlyPendingTimersAsync(); + vi.useRealTimers(); + }); + + test('should create signleton model for the same room', () => { + createModel(); + + const oldModel = model; + + createModel(); + + expect(model).toBe(oldModel); + }); + + test('should create different models for different rooms', () => { + createModel(); + + const anotherModel = model; + + createModel(rooms[1].id); + + expect(model).not.toBe(anotherModel); + }); + + test('should load all activitites', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.activititesAtom); + + await take(ctx, model.activititesAtom); + + expect(track.lastInput()).toStrictEqual(activities.slice(0, 50)); + expect(ctx.get(model.hasItemsAtom)).toBeTruthy(); + expect(ctx.get(model.pagesCountAtom)).toBe(2); + + track.unsubscribe(); + }); + + test('should fetch new data on change params', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.activititesAtom); + + await take(ctx, model.activititesAtom); + + await takeNested(ctx, model.changeFetchActivitiesParams, { + actionIds: [actions[1].id], + }); + + await take(ctx, model.activititesAtom); + + const newActivities = activities + .filter((activity) => activity.action.id === actions[1].id) + .slice(0, 50); + + expect(track.lastInput()).toStrictEqual(newActivities); + expect(ctx.get(model.hasItemsAtom)).toBe(!!newActivities.length); + expect(ctx.get(model.pagesCountAtom)).toBe(2); + + track.unsubscribe(); + }); + + test.skip('should refresh activities every 5 sec', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.activititesAtom); + + await take(ctx, model.activititesAtom); + + const promise = take(ctx, model.activititesAtom); + + await vi.advanceTimersByTimeAsync(5000); + + await expect(promise).resolves.toStrictEqual(activities); + + track.unsubscribe(); + }); +}); diff --git a/src/entities/activities/models/activities/model.ts b/src/entities/activities/models/activities/model.ts new file mode 100644 index 00000000..2da4eea1 --- /dev/null +++ b/src/entities/activities/models/activities/model.ts @@ -0,0 +1,118 @@ +import { + withDataAtom, + withCache, + atom, + withRetry, + withErrorAtom, + reatomRecord, + reatomResource, + action, + withStatusesAtom +} from '@reatom/framework'; +import { molecule, use } from 'bunshi'; + +import { roomModel } from '@/entities/rooms/@x/activities'; + +import { activitiesApi } from '@/shared/api'; +import { constructName, mapStandardResponse, retryQuery } from '@/shared/lib'; +import { Paginated } from '@/shared/types'; + +import { + ActivitiesModel, + Activity, + FetchActivititesParams, + acitivitiesResponseSchema +} from './types'; + +const modelName = 'list'; + +export const Molecule = molecule((): ActivitiesModel => { + const roomId = use(roomModel.Scope); + + const paramsAtom = reatomRecord( + { + page: 1, + actionIds: [], + activistIds: [], + after: null, + before: null, + by: null, + sphereIds: [], + type: null, + count: 50, + }, + constructName(modelName, 'paramsAtom') + ); + + const fetch = reatomResource( + async (ctx) => { + const params = ctx.spy(paramsAtom); + + return ctx.schedule(() => + activitiesApi + .getAll({ ...params, roomId, }, { signal: ctx.controller.signal, }) + .then(acitivitiesResponseSchema.parseAsync) + ); + }, + constructName(modelName, 'fetch') + ).pipe( + withDataAtom( + { items: [], totalCount: 0, limit: 50, } as Paginated, + mapStandardResponse + ), + withCache(), + withRetry(), + withStatusesAtom(), + withErrorAtom(undefined, { initState: null, }) + ); + + const changeFetchActivitiesParams = action( + (ctx, params: FetchActivititesParams) => { + if ('page' in params) { + return paramsAtom.merge(ctx, params); + } + + return paramsAtom.merge(ctx, { ...params, page: 1, }); + }, + constructName(modelName, 'changeFetchActivitiesParams') + ); + + const pendingAtom = atom( + (ctx) => ctx.spy(fetch.statusesAtom).isFirstPending, + constructName(modelName, 'pendingAtom') + ); + const activititesAtom = atom( + (ctx) => ctx.spy(fetch.dataAtom).items, + constructName(modelName, 'activititesAtom') + ); + const hasItemsAtom = atom( + (ctx) => !!ctx.spy(fetch.dataAtom).totalCount, + constructName(modelName, 'hasItemsAtom') + ); + const pagesCountAtom = atom( + (ctx) => { + const { limit, totalCount, } = ctx.spy(fetch.dataAtom); + + return Math.ceil(totalCount / limit); + }, + constructName(modelName, 'pagesCountAtom') + ); + + retryQuery({ + query: fetch, + store: activititesAtom, + timeout: 5000, + }); + + const { retry: refetch, errorAtom, } = fetch; + + return { + changeFetchActivitiesParams, + activititesAtom, + pagesCountAtom, + hasItemsAtom, + pendingAtom, + refetch, + errorAtom, + }; +}); diff --git a/src/entities/activities/models/activities/types.ts b/src/entities/activities/models/activities/types.ts new file mode 100644 index 00000000..b9dfb079 --- /dev/null +++ b/src/entities/activities/models/activities/types.ts @@ -0,0 +1,61 @@ +import { Action, Atom } from '@reatom/framework'; +import zod from 'zod'; + +import { userSchema } from '@/entities/users/@x/activities'; + +import { createPaginationResponseSchema } from '@/shared/lib'; +import { SortDirection } from '@/shared/types'; + +import { ActivityActionId, activityActionSchema } from '../actions'; +import { ActivitySphereId, activitySphereSchema } from '../spheres'; + +export const activitySchema = zod + .object({ + id: zod.number(), + roomId: zod.number(), + activist: userSchema, + action: activityActionSchema, + sphere: activitySphereSchema, + createdAt: zod.string(), + }) + .readonly(); +export const acitivitiesResponseSchema = + createPaginationResponseSchema(activitySchema); + +export interface Activity extends zod.infer {} +export type ActivityId = Activity['id']; + +export type Activities = Activity[]; + +export interface FetchActivititesParams { + /** + * @default 50 + */ + readonly count?: number; + readonly page?: number; + readonly by?: string | null; + readonly type?: SortDirection | null; + readonly before?: string | null; + readonly after?: string | null; + /** + * @todo Extract into new type + */ + readonly activistIds?: number[]; + readonly sphereIds?: ActivitySphereId[]; + readonly actionIds?: ActivityActionId[]; +} + +type ChangeFetchActivitiesParams = Action< + [params: FetchActivititesParams], + FetchActivititesParams +>; + +export interface ActivitiesModel { + readonly activititesAtom: Atom; + readonly errorAtom: Atom; + readonly pagesCountAtom: Atom; + readonly hasItemsAtom: Atom; + readonly pendingAtom: Atom; + readonly refetch: Action; + readonly changeFetchActivitiesParams: ChangeFetchActivitiesParams; +} diff --git a/src/entities/activities/models/index.ts b/src/entities/activities/models/index.ts new file mode 100644 index 00000000..908381d6 --- /dev/null +++ b/src/entities/activities/models/index.ts @@ -0,0 +1,3 @@ +export * from './actions'; +export * from './spheres'; +export * from './activities'; diff --git a/src/entities/activities/models/spheres/index.ts b/src/entities/activities/models/spheres/index.ts new file mode 100644 index 00000000..db14c639 --- /dev/null +++ b/src/entities/activities/models/spheres/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as activitySpheresModel from './model'; diff --git a/src/entities/activities/models/spheres/model.spec.ts b/src/entities/activities/models/spheres/model.spec.ts new file mode 100644 index 00000000..b4a6d898 --- /dev/null +++ b/src/entities/activities/models/spheres/model.spec.ts @@ -0,0 +1,42 @@ +import { getDefaultInjector } from 'bunshi'; +import { beforeEach, describe, expect, test } from 'vitest'; + +import { TestCtx, spheres, createTestCtx, waitNextTick } from '~/test-utils'; + +import { Molecule } from './model'; +import { ActivitySpheresModel } from './types'; + +describe('entities/activitites/models/spheres/model.ts', () => { + let ctx: TestCtx; + let model: ActivitySpheresModel; + + const createModel = () => { + model = getDefaultInjector().get(Molecule); + }; + + beforeEach(() => { + ctx = createTestCtx(); + }); + + test('should create signleton model', () => { + createModel(); + + const oldModel = model; + + createModel(); + + expect(model).toBe(oldModel); + }); + + test('should load all spheres', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.spheresAtom); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual(spheres); + + track.unsubscribe(); + }); +}); diff --git a/src/entities/activities/models/spheres/model.ts b/src/entities/activities/models/spheres/model.ts new file mode 100644 index 00000000..61d34e38 --- /dev/null +++ b/src/entities/activities/models/spheres/model.ts @@ -0,0 +1,55 @@ +import { + atom, + reatomResource, + withCache, + withDataAtom, + withErrorAtom, + withRetry +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { molecule } from 'bunshi'; + +import { activitiesApi } from '@/shared/api'; +import { constructName, mapStandardResponse } from '@/shared/lib'; + +import { + ActivitySpheres, + ActivitySpheresModel, + activitySpheresResponseSchema +} from './types'; + +const modelName = constructName('activitites', 'spheres'); + +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(createMemStorage({ name: modelName, })); + +export const Molecule = molecule((): ActivitySpheresModel => { + const fetch = reatomResource( + async (ctx) => { + return ctx.schedule(() => + activitiesApi + .getSpheres({ signal: ctx.controller.signal, }) + .then(activitySpheresResponseSchema.parseAsync) + ); + }, + constructName(modelName, 'fetch') + ).pipe( + withDataAtom([] as ActivitySpheres, mapStandardResponse), + withCache({ withPersist, }), + withRetry(), + withErrorAtom(undefined, { initState: null, }) + ); + + const { dataAtom: spheresAtom, errorAtom, } = fetch; + + const pendingAtom = atom( + (ctx) => !!ctx.spy(fetch.pendingAtom), + constructName(modelName, 'pendingAtom') + ); + + return { + spheresAtom, + errorAtom, + pendingAtom, + }; +}); diff --git a/src/entities/activities/models/spheres/types.ts b/src/entities/activities/models/spheres/types.ts new file mode 100644 index 00000000..8e60256d --- /dev/null +++ b/src/entities/activities/models/spheres/types.ts @@ -0,0 +1,27 @@ +import { Atom } from '@reatom/framework'; +import zod from 'zod'; + +import { createStandardResponseSchema } from '@/shared/lib'; + +export const activitySphereSchema = zod + .object({ + id: zod.number(), + name: zod.string(), + }) + .readonly(); +export const activitySpheresSchema = zod.array(activitySphereSchema); +export const activitySpheresResponseSchema = createStandardResponseSchema( + activitySpheresSchema +); + +export interface ActivitySphere + extends zod.infer {} +export type ActivitySphereId = ActivitySphere['id']; + +export type ActivitySpheres = ActivitySphere[]; + +export interface ActivitySpheresModel { + readonly spheresAtom: Atom; + readonly errorAtom: Atom; + readonly pendingAtom: Atom; +} diff --git a/src/entities/activities/ui/activities-actions-picker/activities-actions-picker.tsx b/src/entities/activities/ui/activities-actions-picker/activities-actions-picker.tsx index 8268ce9b..220a1b31 100644 --- a/src/entities/activities/ui/activities-actions-picker/activities-actions-picker.tsx +++ b/src/entities/activities/ui/activities-actions-picker/activities-actions-picker.tsx @@ -5,35 +5,50 @@ import { ListItemAvatar, ListItemText } from '@mui/material'; -import * as React from 'react'; +import { FC, memo } from 'react'; import { useTranslation } from 'react-i18next'; -import { ActivityAction } from '@/shared/api'; import { preparePickerHandler, preparePickerSelectedValue } from '@/shared/lib'; -import { CommonProps, PickerProps } from '@/shared/types'; -import { Field, FieldProps } from '@/shared/ui'; +import type { CommonProps, PickerProps } from '@/shared/types'; +import { Field, type FieldProps } from '@/shared/ui'; -import { useActivityActions } from '../../lib'; -import { ActivityActionPicture } from '../activity-action-picture'; +import type { ActivityActionId, ActivityActions } from '../../models'; +import { ActivityActionIcon } from '../activity-action-icon'; export type ActivitiesActionsPickerProps = CommonProps & - PickerProps & - Omit; + PickerProps & + Omit & { + readonly actions: ActivityActions; + readonly loading?: boolean; + }; -export const ActivitiesActionsPicker: React.FC = - React.memo((props) => { - const { value, onChange, className, multiple, limitTags, ...rest } = props; - const actions = useActivityActions(); +export const ActivitiesActionsPicker: FC = memo( + (props) => { + const { + value, + onChange, + className, + multiple, + limitTags, + actions, + loading, + ...rest + } = props; const { t, } = useTranslation('activities'); - const changeHandler = preparePickerHandler( - { multiple, onChange, }, + const handleChange = preparePickerHandler( + { + onChange, + multiple, + }, 'id' ); - const selected = preparePickerSelectedValue( - { value, multiple, }, - actions.data, + { + value, + multiple, + }, + actions, 'id' ); @@ -44,10 +59,10 @@ export const ActivitiesActionsPicker: React.FC = return ( actions.name} renderOption={(props, option) => { const activity = translate(option.name); @@ -55,7 +70,7 @@ export const ActivitiesActionsPicker: React.FC = return ( - + {activity} @@ -77,4 +92,5 @@ export const ActivitiesActionsPicker: React.FC = multiple={multiple} /> ); - }); + } +); diff --git a/src/entities/activities/ui/activities-spheres-picker/activities-spheres-picker.tsx b/src/entities/activities/ui/activities-spheres-picker/activities-spheres-picker.tsx index f06216d0..4f8c1505 100644 --- a/src/entities/activities/ui/activities-spheres-picker/activities-spheres-picker.tsx +++ b/src/entities/activities/ui/activities-spheres-picker/activities-spheres-picker.tsx @@ -1,32 +1,47 @@ import { Autocomplete, Chip, ListItem, ListItemText } from '@mui/material'; -import * as React from 'react'; +import { memo, FC } from 'react'; import { useTranslation } from 'react-i18next'; -import { ActivitySphere } from '@/shared/api'; import { preparePickerHandler, preparePickerSelectedValue } from '@/shared/lib'; -import { CommonProps, PickerProps } from '@/shared/types'; -import { Field, FieldProps } from '@/shared/ui'; +import type { CommonProps, PickerProps } from '@/shared/types'; +import { Field, type FieldProps } from '@/shared/ui'; -import { useActivitySpheres } from '../../lib'; +import type { ActivitySphereId, ActivitySpheres } from '../../models'; export type ActivitiesSpheresPickerProps = CommonProps & - PickerProps & - Omit; + PickerProps & + Omit & { + readonly spheres: ActivitySpheres; + readonly loading?: boolean; + }; -export const ActivitiesSpheresPicker: React.FC = - React.memo((props) => { - const { value, onChange, multiple, limitTags, className, ...rest } = props; - const spheres = useActivitySpheres(); +export const ActivitiesSpheresPicker: FC = memo( + (props) => { + const { + value, + onChange, + multiple, + limitTags, + className, + spheres, + loading, + ...rest + } = props; const { t, } = useTranslation('activities'); - const changeHandler = preparePickerHandler( - { multiple, onChange, }, + const handleChange = preparePickerHandler( + { + onChange, + multiple, + }, 'id' ); - const selected = preparePickerSelectedValue( - { value, multiple, }, - spheres.data, + { + value, + multiple, + }, + spheres, 'id' ); @@ -37,10 +52,10 @@ export const ActivitiesSpheresPicker: React.FC = return ( sphere.name} renderInput={(params) => { return ; @@ -67,4 +82,5 @@ export const ActivitiesSpheresPicker: React.FC = multiple={multiple} /> ); - }); + } +); diff --git a/src/entities/activities/ui/activity-action-icon/__snapshots__/activity-action-icon.spec.tsx.snap b/src/entities/activities/ui/activity-action-icon/__snapshots__/activity-action-icon.spec.tsx.snap new file mode 100644 index 00000000..d47485b6 --- /dev/null +++ b/src/entities/activities/ui/activity-action-icon/__snapshots__/activity-action-icon.spec.tsx.snap @@ -0,0 +1,58 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/activities/ui/activity-action-icon/activity-action-icon > should render icon for \`create\` action > create 1`] = ` +
+ +
+`; + +exports[`entities/activities/ui/activity-action-icon/activity-action-icon > should render icon for \`remove\` action > remove 1`] = ` +
+ +
+`; + +exports[`entities/activities/ui/activity-action-icon/activity-action-icon > should render icon for \`update\` action > update 1`] = ` +
+ +
+`; diff --git a/src/entities/activities/ui/activity-action-icon/activity-action-icon.spec.tsx b/src/entities/activities/ui/activity-action-icon/activity-action-icon.spec.tsx new file mode 100644 index 00000000..cd78dd1e --- /dev/null +++ b/src/entities/activities/ui/activity-action-icon/activity-action-icon.spec.tsx @@ -0,0 +1,27 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, render } from '~/test-utils'; + +import { ActivityActionIcon } from './activity-action-icon'; + + +describe('entities/activities/ui/activity-action-icon/activity-action-icon', () => { + let wrapper: RenderResult; + + const createComponent = (action: string) => { + wrapper = render( + + ); + }; + + const getIcon = () => wrapper.container.querySelector('div')!; + + test.each(['create', 'remove', 'update'])( + 'should render icon for `%s` action', + (action) => { + createComponent(action); + + expect(getIcon()).toMatchSnapshot(action); + } + ); +}); diff --git a/src/entities/activities/ui/activity-action-icon/activity-action-icon.tsx b/src/entities/activities/ui/activity-action-icon/activity-action-icon.tsx new file mode 100644 index 00000000..1dac5609 --- /dev/null +++ b/src/entities/activities/ui/activity-action-icon/activity-action-icon.tsx @@ -0,0 +1,45 @@ +import AddIcon from '@mui/icons-material/Add'; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import { Avatar } from '@mui/material'; +import cn from 'classnames'; +import { type FC, memo, type ReactNode } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { CommonProps } from '@/shared/types'; + +import styles from './styles.module.css'; + +export interface ActivityActionIconProps extends CommonProps { + readonly action: string; +} + +const colorMap: Record = { + create: 'success', + remove: 'error', + update: 'warning', +}; + +const iconMap: Record = { + create: , + remove: , + update: , +}; + +export const ActivityActionIcon: FC = memo((props) => { + const { action, className, } = props; + const { t, } = useTranslation('activities'); + + const labelT = t(`type.${action}`)!; + + const icon = iconMap[action]; + + return ( + + {icon} + + ); +}); diff --git a/src/entities/activities/ui/activity-action-icon/index.ts b/src/entities/activities/ui/activity-action-icon/index.ts new file mode 100644 index 00000000..9d8229e3 --- /dev/null +++ b/src/entities/activities/ui/activity-action-icon/index.ts @@ -0,0 +1,4 @@ +export { + ActivityActionIcon, + type ActivityActionIconProps +} from './activity-action-icon'; diff --git a/src/entities/activities/ui/activity-action-picture/activity-action-picture.module.css b/src/entities/activities/ui/activity-action-icon/styles.module.css similarity index 100% rename from src/entities/activities/ui/activity-action-picture/activity-action-picture.module.css rename to src/entities/activities/ui/activity-action-icon/styles.module.css diff --git a/src/entities/activities/ui/activity-action-picture/activity-action-picture.module.css.d.ts b/src/entities/activities/ui/activity-action-icon/styles.module.css.d.ts similarity index 100% rename from src/entities/activities/ui/activity-action-picture/activity-action-picture.module.css.d.ts rename to src/entities/activities/ui/activity-action-icon/styles.module.css.d.ts diff --git a/src/entities/activities/ui/activity-action-picture/activity-action-picture.tsx b/src/entities/activities/ui/activity-action-picture/activity-action-picture.tsx deleted file mode 100644 index 51625420..00000000 --- a/src/entities/activities/ui/activity-action-picture/activity-action-picture.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import AddIcon from '@mui/icons-material/Add'; -import DeleteIcon from '@mui/icons-material/Delete'; -import EditIcon from '@mui/icons-material/Edit'; -import { Avatar } from '@mui/material'; -import cn from 'classnames'; -import * as React from 'react'; -import { useTranslation } from 'react-i18next'; - -import { ActivityAction } from '@/shared/api'; -import { CommonProps } from '@/shared/types'; - -import styles from './activity-action-picture.module.css'; - -export interface ActivityActionPictureProps - extends CommonProps, - ActivityAction {} - -const colorMap: Record = { - create: 'success', - remove: 'error', - update: 'warning', -}; - -const iconMap: Record = { - create: , - remove: , - update: , -}; - -export const ActivityActionPicture: React.FC = - React.memo((props) => { - const { name, className, } = props; - const { t, } = useTranslation('activities'); - - const label = t(`type.${name}`)!; - - return ( - - {iconMap[name]} - - ); - }); diff --git a/src/entities/activities/ui/activity-action-picture/index.ts b/src/entities/activities/ui/activity-action-picture/index.ts deleted file mode 100644 index 8f7ad465..00000000 --- a/src/entities/activities/ui/activity-action-picture/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - ActivityActionPicture, - type ActivityActionPictureProps -} from './activity-action-picture'; diff --git a/src/entities/activities/ui/activity-list-item-skeleton/__snapshots__/skeleton-activity-list-item.spec.tsx.snap b/src/entities/activities/ui/activity-list-item-skeleton/__snapshots__/skeleton-activity-list-item.spec.tsx.snap new file mode 100644 index 00000000..1451587a --- /dev/null +++ b/src/entities/activities/ui/activity-list-item-skeleton/__snapshots__/skeleton-activity-list-item.spec.tsx.snap @@ -0,0 +1,51 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/activities/ui/activity-list-item-skeleton/activity-list-item-skeleton.tsx > should render skeleton of activity list item 1`] = ` +
  • +
    + +
    + +
    +
    +
    +
    + + + +

    + +

    +
    +
  • +`; diff --git a/src/entities/activities/ui/skeleton-activity-list-item/skeleton-activity-list-item.tsx b/src/entities/activities/ui/activity-list-item-skeleton/activity-list-item-skeleton.tsx similarity index 68% rename from src/entities/activities/ui/skeleton-activity-list-item/skeleton-activity-list-item.tsx rename to src/entities/activities/ui/activity-list-item-skeleton/activity-list-item-skeleton.tsx index 0764b567..23ebf794 100644 --- a/src/entities/activities/ui/skeleton-activity-list-item/skeleton-activity-list-item.tsx +++ b/src/entities/activities/ui/activity-list-item-skeleton/activity-list-item-skeleton.tsx @@ -7,18 +7,18 @@ import { Skeleton } from '@mui/material'; import cn from 'classnames'; -import * as React from 'react'; +import { type FC, memo } from 'react'; import { CommonProps } from '@/shared/types'; -import styles from './skeleton-activity-list-item.module.css'; +import styles from './styles.module.css'; -export interface SkeletonActivityListItemProps +export interface ActivityListItemSkeletonProps extends CommonProps, ListItemProps {} -export const SkeletonActivityListItem: React.FC = - React.memo(function SkeletonActivityCard(props) { +export const ActivityListItemSkeleton: FC = memo( + (props) => { const { className, ...rest } = props; return ( @@ -33,4 +33,5 @@ export const SkeletonActivityListItem: React.FC = /> ); - }); + } +); diff --git a/src/entities/activities/ui/activity-list-item-skeleton/index.ts b/src/entities/activities/ui/activity-list-item-skeleton/index.ts new file mode 100644 index 00000000..113387de --- /dev/null +++ b/src/entities/activities/ui/activity-list-item-skeleton/index.ts @@ -0,0 +1 @@ +export * from './activity-list-item-skeleton'; diff --git a/src/entities/activities/ui/activity-list-item-skeleton/skeleton-activity-list-item.spec.tsx b/src/entities/activities/ui/activity-list-item-skeleton/skeleton-activity-list-item.spec.tsx new file mode 100644 index 00000000..f21c880a --- /dev/null +++ b/src/entities/activities/ui/activity-list-item-skeleton/skeleton-activity-list-item.spec.tsx @@ -0,0 +1,22 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, render } from '~/test-utils'; + +import { ActivityListItemSkeleton } from './activity-list-item-skeleton'; + + +describe('entities/activities/ui/activity-list-item-skeleton/activity-list-item-skeleton.tsx', () => { + let wrapper: RenderResult; + + const createComponent = () => { + wrapper = render(); + }; + + const findItem = () => wrapper.getByRole('listitem'); + + test('should render skeleton of activity list item', () => { + createComponent(); + + expect(findItem()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/activities/ui/skeleton-activity-list-item/skeleton-activity-list-item.module.css b/src/entities/activities/ui/activity-list-item-skeleton/styles.module.css similarity index 99% rename from src/entities/activities/ui/skeleton-activity-list-item/skeleton-activity-list-item.module.css rename to src/entities/activities/ui/activity-list-item-skeleton/styles.module.css index 3765ef01..674d5666 100644 --- a/src/entities/activities/ui/skeleton-activity-list-item/skeleton-activity-list-item.module.css +++ b/src/entities/activities/ui/activity-list-item-skeleton/styles.module.css @@ -11,6 +11,5 @@ .block { grid-row: span 2; - width: 100%; } diff --git a/src/entities/activities/ui/skeleton-activity-list-item/skeleton-activity-list-item.module.css.d.ts b/src/entities/activities/ui/activity-list-item-skeleton/styles.module.css.d.ts similarity index 100% rename from src/entities/activities/ui/skeleton-activity-list-item/skeleton-activity-list-item.module.css.d.ts rename to src/entities/activities/ui/activity-list-item-skeleton/styles.module.css.d.ts diff --git a/src/entities/activities/ui/activity-list-item/__snapshots__/activity-list-item.spec.tsx.snap b/src/entities/activities/ui/activity-list-item/__snapshots__/activity-list-item.spec.tsx.snap new file mode 100644 index 00000000..2d4f25f1 --- /dev/null +++ b/src/entities/activities/ui/activity-list-item/__snapshots__/activity-list-item.spec.tsx.snap @@ -0,0 +1,48 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/activities/ui/activity-list-item/activity-list-item > should render activity list item 1`] = ` +
  • +
    +
    + +
    +
    +
    + + card.text + +

    + +

    +
    +
  • +`; diff --git a/src/entities/activities/ui/activity-list-item/activity-list-item.spec.tsx b/src/entities/activities/ui/activity-list-item/activity-list-item.spec.tsx new file mode 100644 index 00000000..a334c01d --- /dev/null +++ b/src/entities/activities/ui/activity-list-item/activity-list-item.spec.tsx @@ -0,0 +1,34 @@ +import { List } from '@mui/material'; +import { describe, expect, test } from 'vitest'; + +import { RenderResult, activities, render } from '~/test-utils'; + +import { ActivityListItem } from './activity-list-item'; + + +describe('entities/activities/ui/activity-list-item/activity-list-item', () => { + let wrapper: RenderResult; + + const createComponent = () => { + wrapper = render( + , + { + wrapper: List, + } + ); + }; + + const findItem = () => wrapper.getByRole('listitem'); + + test('should render activity list item', () => { + createComponent(); + + expect(findItem()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/activities/ui/activity-list-item/activity-list-item.tsx b/src/entities/activities/ui/activity-list-item/activity-list-item.tsx index 8406fb0f..95223a38 100644 --- a/src/entities/activities/ui/activity-list-item/activity-list-item.tsx +++ b/src/entities/activities/ui/activity-list-item/activity-list-item.tsx @@ -8,30 +8,24 @@ import cn from 'classnames'; import * as React from 'react'; import { useTranslation } from 'react-i18next'; -import { Activity } from '@/shared/api'; import { CommonProps } from '@/shared/types'; import { DateTime } from '@/shared/ui'; -import { ActivityActionPicture } from '../activity-action-picture'; +import { Activity } from '../../models'; +import { ActivityActionIcon } from '../activity-action-icon'; -import styles from './activity-list-item.module.css'; +import styles from './styles.module.css'; export interface ActivityListItemProps extends CommonProps, - Activity, - Omit {} + Pick, + ListItemProps {} +/** + * @todo Rework props. Stay only needed + */ export const ActivityListItem: React.FC = (props) => { - const { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - id: _, - action, - sphere, - className, - createdAt, - activist, - ...rest - } = props; + const { action, sphere, className, createdAt, activist, ...rest } = props; const { t, } = useTranslation('activities'); const activityText = t('card.text', { type: action.name, @@ -42,7 +36,7 @@ export const ActivityListItem: React.FC = (props) => { return ( - + { - return useUnit(commentsModel.query); -}; diff --git a/src/entities/comments/model/comments.ts b/src/entities/comments/model/comments.ts deleted file mode 100644 index b9531fca..00000000 --- a/src/entities/comments/model/comments.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { cache, createQuery } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createDomain } from 'effector'; -import { Array } from 'runtypes'; - -import { Comment, comment, commentsApi } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { getStandardResponse } from '@/shared/types'; - -const commentsDomain = createDomain(); - -const handlerFx = commentsDomain.effect(commentsApi.getAll); - -export const query = createQuery({ - initialData: [] as Comment[], - effect: handlerFx, - contract: runtypeContract(getStandardResponse(Array(comment))), - mapData: extractData, -}); - -cache(query); diff --git a/src/entities/comments/model/index.ts b/src/entities/comments/model/index.ts deleted file mode 100644 index 578defde..00000000 --- a/src/entities/comments/model/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * as commentsModel from './comments'; diff --git a/src/entities/comments/ui/index.ts b/src/entities/comments/ui/index.ts deleted file mode 100644 index 0d0f780a..00000000 --- a/src/entities/comments/ui/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './template-comment-card'; diff --git a/src/entities/comments/ui/template-comment-card/index.ts b/src/entities/comments/ui/template-comment-card/index.ts deleted file mode 100644 index ef9269b4..00000000 --- a/src/entities/comments/ui/template-comment-card/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - TemplateCommentCard, - type TemplateCommentCardProps -} from './template-comment-card'; diff --git a/src/entities/comments/ui/template-comment-card/template-comment-card.tsx b/src/entities/comments/ui/template-comment-card/template-comment-card.tsx deleted file mode 100644 index 410be55c..00000000 --- a/src/entities/comments/ui/template-comment-card/template-comment-card.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { Card, CardContent, Typography } from '@mui/material'; -import * as React from 'react'; - -import { Comment } from '@/shared/api'; -import { CommonProps } from '@/shared/types'; - -export interface TemplateCommentCardProps extends CommonProps, Comment { - readonly actions?: React.ReactElement | null; -} - -export const TemplateCommentCard: React.FC = ( - props -) => { - const { content, className, } = props; - - return ( - - - {content} - - - ); -}; diff --git a/src/entities/invitations/ui/index.ts b/src/entities/invitations/ui/index.ts index 4c9f5a35..b29bd5b3 100644 --- a/src/entities/invitations/ui/index.ts +++ b/src/entities/invitations/ui/index.ts @@ -1,4 +1,4 @@ -export * from './template-invitation-list-item'; -export * from './skeleton-invitation-list-item'; -export * from './template-invitation-card'; -export * from './skeleton-invitation-card'; +export * from './invitation-card-template'; +export * from './invitation-card-skeleton'; +export * from './invitation-list-item-skeleton'; +export * from './invitation-list-item-template'; diff --git a/src/entities/invitations/ui/invitation-card-skeleton/__snapshots__/invitation-card-skeleton.spec.tsx.snap b/src/entities/invitations/ui/invitation-card-skeleton/__snapshots__/invitation-card-skeleton.spec.tsx.snap new file mode 100644 index 00000000..8b86a799 --- /dev/null +++ b/src/entities/invitations/ui/invitation-card-skeleton/__snapshots__/invitation-card-skeleton.spec.tsx.snap @@ -0,0 +1,93 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/invitations/ui/invitation-card-skeleton/invitation-card-skeleton.tsx > should render correctly 1`] = ` +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    + +
    + +
    +
    + + +
    + +
    +
    +
    + +
    +`; diff --git a/src/entities/invitations/ui/invitation-card-skeleton/index.ts b/src/entities/invitations/ui/invitation-card-skeleton/index.ts new file mode 100644 index 00000000..25a3264a --- /dev/null +++ b/src/entities/invitations/ui/invitation-card-skeleton/index.ts @@ -0,0 +1 @@ +export * from './invitation-card-skeleton'; diff --git a/src/entities/invitations/ui/invitation-card-skeleton/invitation-card-skeleton.spec.tsx b/src/entities/invitations/ui/invitation-card-skeleton/invitation-card-skeleton.spec.tsx new file mode 100644 index 00000000..0ace4b9e --- /dev/null +++ b/src/entities/invitations/ui/invitation-card-skeleton/invitation-card-skeleton.spec.tsx @@ -0,0 +1,21 @@ +import { describe, test, expect } from 'vitest'; + +import { RenderResult, render } from '~/test-utils'; + +import { InvitationCardSkeleton } from './invitation-card-skeleton'; + +describe('entities/invitations/ui/invitation-card-skeleton/invitation-card-skeleton.tsx', () => { + let wrapper: RenderResult; + + const createComponent = () => { + wrapper = render(); + }; + + const findCard = () => wrapper.container.querySelector('div')!; + + test('should render correctly', () => { + createComponent(); + + expect(findCard()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/invitations/ui/invitation-card-skeleton/invitation-card-skeleton.tsx b/src/entities/invitations/ui/invitation-card-skeleton/invitation-card-skeleton.tsx new file mode 100644 index 00000000..60b60bbb --- /dev/null +++ b/src/entities/invitations/ui/invitation-card-skeleton/invitation-card-skeleton.tsx @@ -0,0 +1,41 @@ +import { + Avatar, + Card, + CardContent, + CardHeader, + Skeleton, + type CardProps +} from '@mui/material'; +import { type FC, memo } from 'react'; + +import type { CommonProps } from '@/shared/types'; + +export interface InvitationCardSkeletonProps extends CommonProps, CardProps {} + +export const InvitationCardSkeleton: FC = memo( + (props) => { + return ( + + + + + } + title={} + disableTypography + /> + + + + + + + + + + + + ); + } +); diff --git a/src/entities/invitations/ui/invitation-card-template/__snapshots__/invitation-card-template.spec.tsx.snap b/src/entities/invitations/ui/invitation-card-template/__snapshots__/invitation-card-template.spec.tsx.snap new file mode 100644 index 00000000..b45253de --- /dev/null +++ b/src/entities/invitations/ui/invitation-card-template/__snapshots__/invitation-card-template.spec.tsx.snap @@ -0,0 +1,131 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/invitations/ui/invitation-card-template/invitation-card-template.tsx > should render actions if they are provided > with actions 1`] = ` +
    +
    +
    +
    + Inviter avatar +
    +
    +
    + + card.title + +
    +
    +
    +
    +
    + Inviter avatar +
    +

    + c + + a + + r + + d + + . + + t + +

    +
    + User avatar +
    +
    +
    +
    +
    + + +
    +
    +
    +`; + +exports[`entities/invitations/ui/invitation-card-template/invitation-card-template.tsx > should render correctly > default 1`] = ` +
    +
    +
    +
    + Inviter avatar +
    +
    +
    + + card.title + +
    +
    +
    +
    +
    + Inviter avatar +
    +

    + c + + a + + r + + d + + . + + t + +

    +
    + User avatar +
    +
    +
    +
    +`; diff --git a/src/entities/invitations/ui/invitation-card-template/index.ts b/src/entities/invitations/ui/invitation-card-template/index.ts new file mode 100644 index 00000000..74311742 --- /dev/null +++ b/src/entities/invitations/ui/invitation-card-template/index.ts @@ -0,0 +1 @@ +export * from './invitation-card-template'; diff --git a/src/entities/invitations/ui/invitation-card-template/invitation-card-template.spec.tsx b/src/entities/invitations/ui/invitation-card-template/invitation-card-template.spec.tsx new file mode 100644 index 00000000..3d5ceea6 --- /dev/null +++ b/src/entities/invitations/ui/invitation-card-template/invitation-card-template.spec.tsx @@ -0,0 +1,60 @@ +import { describe, test, expect } from 'vitest'; + +import { RenderResult, defaultInvitation, render } from '~/test-utils'; + +import { DeepPartial } from '@/shared/types'; + +import { + InvitationCardTemplate, + InvitationCardTemplateProps +} from './invitation-card-template'; + + +describe('entities/invitations/ui/invitation-card-template/invitation-card-template.tsx', () => { + let wrapper: RenderResult; + + const defaultProps: InvitationCardTemplateProps = { + inviterName: defaultInvitation.inviter.username, + roomName: defaultInvitation.room.description, + username: defaultInvitation.user!.username, + slots: { + inviterAvatar:
    Inviter avatar
    , + userAvatar:
    User avatar
    , + }, + }; + + const createComponent = ( + props: DeepPartial = {} + ) => { + wrapper = render( + + ); + }; + + const findCard = () => wrapper.container.querySelector('div')!; + + test('should render correctly', () => { + createComponent(); + + expect(findCard()).toMatchSnapshot('default'); + }); + + test('should render actions if they are provided', () => { + createComponent({ + slots: { + actions: ( +
    + + +
    + ), + }, + }); + + expect(findCard()).toMatchSnapshot('with actions'); + }); +}); diff --git a/src/entities/invitations/ui/template-invitation-card/ui.tsx b/src/entities/invitations/ui/invitation-card-template/invitation-card-template.tsx similarity index 72% rename from src/entities/invitations/ui/template-invitation-card/ui.tsx rename to src/entities/invitations/ui/invitation-card-template/invitation-card-template.tsx index f1a7985f..d366d800 100644 --- a/src/entities/invitations/ui/template-invitation-card/ui.tsx +++ b/src/entities/invitations/ui/invitation-card-template/invitation-card-template.tsx @@ -3,26 +3,28 @@ import { CardActions, CardContent, CardHeader, + CardProps, Typography } from '@mui/material'; import cn from 'classnames'; -import * as React from 'react'; +import type { FC } from 'react'; import { useTranslation } from 'react-i18next'; -import { CommonProps, Slots } from '@/shared/types'; +import type { CommonProps, Slots } from '@/shared/types'; -import styles from './ui.module.css'; +import styles from './styles.module.css'; +type CardSlots = 'userAvatar' | 'inviterAvatar' | 'actions'; +type RequiredCardSlots = Extract; -export interface TemplateInvitationCardProps extends CommonProps { - readonly slots: Required> & - Slots<'actions'>; +export interface InvitationCardTemplateProps extends CommonProps, CardProps { + readonly slots: Slots; readonly inviterName: string; readonly username: string; readonly roomName: string; } -export const TemplateInvitationCard: React.FC = ( +export const InvitationCardTemplate: FC = ( props ) => { const { inviterName, roomName, slots, username, className, } = props; diff --git a/src/entities/invitations/ui/template-invitation-card/ui.module.css b/src/entities/invitations/ui/invitation-card-template/styles.module.css similarity index 88% rename from src/entities/invitations/ui/template-invitation-card/ui.module.css rename to src/entities/invitations/ui/invitation-card-template/styles.module.css index 59172285..9f25b8ff 100644 --- a/src/entities/invitations/ui/template-invitation-card/ui.module.css +++ b/src/entities/invitations/ui/invitation-card-template/styles.module.css @@ -1,17 +1,15 @@ .card { max-width: 560px; - } .content { display: flex; - align-items: center; gap: 1em; + align-items: center; } .text { max-width: 250px; - text-align: center; } diff --git a/src/entities/invitations/ui/template-invitation-card/ui.module.css.d.ts b/src/entities/invitations/ui/invitation-card-template/styles.module.css.d.ts similarity index 100% rename from src/entities/invitations/ui/template-invitation-card/ui.module.css.d.ts rename to src/entities/invitations/ui/invitation-card-template/styles.module.css.d.ts diff --git a/src/entities/invitations/ui/invitation-list-item-skeleton/__snapshots__/invitation-list-item-skeleton.spec.tsx.snap b/src/entities/invitations/ui/invitation-list-item-skeleton/__snapshots__/invitation-list-item-skeleton.spec.tsx.snap new file mode 100644 index 00000000..5d2588e0 --- /dev/null +++ b/src/entities/invitations/ui/invitation-list-item-skeleton/__snapshots__/invitation-list-item-skeleton.spec.tsx.snap @@ -0,0 +1,27 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/invitations/ui/invitation-list-item-skeleton/invitation-list-item-skeleton.tsx > should render correctly 1`] = ` +
    + +
    + +
    +
    +
    +`; diff --git a/src/entities/invitations/ui/invitation-list-item-skeleton/index.ts b/src/entities/invitations/ui/invitation-list-item-skeleton/index.ts new file mode 100644 index 00000000..14b83882 --- /dev/null +++ b/src/entities/invitations/ui/invitation-list-item-skeleton/index.ts @@ -0,0 +1 @@ +export * from './invitation-list-item-skeleton'; diff --git a/src/entities/invitations/ui/invitation-list-item-skeleton/invitation-list-item-skeleton.spec.tsx b/src/entities/invitations/ui/invitation-list-item-skeleton/invitation-list-item-skeleton.spec.tsx new file mode 100644 index 00000000..38c6aa21 --- /dev/null +++ b/src/entities/invitations/ui/invitation-list-item-skeleton/invitation-list-item-skeleton.spec.tsx @@ -0,0 +1,21 @@ +import { describe, test, expect } from 'vitest'; + +import { RenderResult, render } from '~/test-utils'; + +import { InvitationListItemSkeleton } from './invitation-list-item-skeleton'; + +describe('entities/invitations/ui/invitation-list-item-skeleton/invitation-list-item-skeleton.tsx', () => { + let wrapper: RenderResult; + + const createComponent = () => { + wrapper = render(); + }; + + const findCard = () => wrapper.container.querySelector('div')!; + + test('should render correctly', () => { + createComponent(); + + expect(findCard()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/invitations/ui/invitation-list-item-skeleton/invitation-list-item-skeleton.tsx b/src/entities/invitations/ui/invitation-list-item-skeleton/invitation-list-item-skeleton.tsx new file mode 100644 index 00000000..5138035e --- /dev/null +++ b/src/entities/invitations/ui/invitation-list-item-skeleton/invitation-list-item-skeleton.tsx @@ -0,0 +1,38 @@ +import { + Avatar, + ListItem, + ListItemAvatar, + ListItemText, + Skeleton, + type ListItemProps +} from '@mui/material'; +import cn from 'classnames'; +import { memo, type FC } from 'react'; + +import type { CommonProps } from '@/shared/types'; + +import styles from './styles.module.css'; + +export interface InvitationListItemSkeletonProps + extends CommonProps, + ListItemProps {} + +export const InvitationListItemSkeleton: FC = + memo((props) => { + const { className, ...rest } = props; + + return ( + + + + + + + } + secondary={} + primaryTypographyProps={{ variant: 'subtitle1', component: 'p', }} + /> + + ); + }); diff --git a/src/entities/invitations/ui/skeleton-invitation-list-item/skeleton-invitation-list-item.module.css b/src/entities/invitations/ui/invitation-list-item-skeleton/styles.module.css similarity index 100% rename from src/entities/invitations/ui/skeleton-invitation-list-item/skeleton-invitation-list-item.module.css rename to src/entities/invitations/ui/invitation-list-item-skeleton/styles.module.css diff --git a/src/entities/invitations/ui/skeleton-invitation-list-item/skeleton-invitation-list-item.module.css.d.ts b/src/entities/invitations/ui/invitation-list-item-skeleton/styles.module.css.d.ts similarity index 100% rename from src/entities/invitations/ui/skeleton-invitation-list-item/skeleton-invitation-list-item.module.css.d.ts rename to src/entities/invitations/ui/invitation-list-item-skeleton/styles.module.css.d.ts diff --git a/src/entities/invitations/ui/invitation-list-item-template/__snapshots__/invitation-list-item-template.spec.tsx.snap b/src/entities/invitations/ui/invitation-list-item-template/__snapshots__/invitation-list-item-template.spec.tsx.snap new file mode 100644 index 00000000..21769b13 --- /dev/null +++ b/src/entities/invitations/ui/invitation-list-item-template/__snapshots__/invitation-list-item-template.spec.tsx.snap @@ -0,0 +1,39 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/invitations/ui/invitation-list-item-template/invitation-list-item-template.tsx > should render actions if they are provided > with actions 1`] = ` +
    +
    +
    + User avatar +
    +
    +
    + + Cool-user + +

    + list.item.inviter +

    +
    +
    +`; + +exports[`entities/invitations/ui/invitation-list-item-template/invitation-list-item-template.tsx > should render correctly > default 1`] = ` +
    +
    + User avatar +
    +
    +`; diff --git a/src/entities/invitations/ui/invitation-list-item-template/index.ts b/src/entities/invitations/ui/invitation-list-item-template/index.ts new file mode 100644 index 00000000..80a748a7 --- /dev/null +++ b/src/entities/invitations/ui/invitation-list-item-template/index.ts @@ -0,0 +1 @@ +export * from './invitation-list-item-template'; diff --git a/src/entities/invitations/ui/invitation-list-item-template/invitation-list-item-template.spec.tsx b/src/entities/invitations/ui/invitation-list-item-template/invitation-list-item-template.spec.tsx new file mode 100644 index 00000000..fe76b96f --- /dev/null +++ b/src/entities/invitations/ui/invitation-list-item-template/invitation-list-item-template.spec.tsx @@ -0,0 +1,58 @@ +import { describe, test, expect } from 'vitest'; + +import { RenderResult, defaultInvitation, render } from '~/test-utils'; + +import { DeepPartial } from '@/shared/types'; + +import { + InvitationListItemTemplate, + InvitationListItemTemplateProps +} from './invitation-list-item-template'; + + +describe('entities/invitations/ui/invitation-list-item-template/invitation-list-item-template.tsx', () => { + let wrapper: RenderResult; + + const defaultProps: InvitationListItemTemplateProps = { + inviterName: defaultInvitation.inviter.username, + username: defaultInvitation.user!.username, + slots: { + userAvatar:
    User avatar
    , + }, + }; + + const createComponent = ( + props: DeepPartial = {} + ) => { + wrapper = render( + + ); + }; + + const findCard = () => wrapper.container.querySelector('div')!; + + test('should render correctly', () => { + createComponent(); + + expect(findCard()).toMatchSnapshot('default'); + }); + + test('should render actions if they are provided', () => { + createComponent({ + slots: { + actions: ( +
    + + +
    + ), + }, + }); + + expect(findCard()).toMatchSnapshot('with actions'); + }); +}); diff --git a/src/entities/invitations/ui/template-invitation-list-item/template-invitation-list-item.tsx b/src/entities/invitations/ui/invitation-list-item-template/invitation-list-item-template.tsx similarity index 64% rename from src/entities/invitations/ui/template-invitation-list-item/template-invitation-list-item.tsx rename to src/entities/invitations/ui/invitation-list-item-template/invitation-list-item-template.tsx index 6e90a69c..60d4090a 100644 --- a/src/entities/invitations/ui/template-invitation-list-item/template-invitation-list-item.tsx +++ b/src/entities/invitations/ui/invitation-list-item-template/invitation-list-item-template.tsx @@ -1,25 +1,27 @@ import { ListItem, ListItemAvatar, - ListItemProps, ListItemSecondaryAction, - ListItemText + ListItemText, + type ListItemProps } from '@mui/material'; -import { FC } from 'react'; +import type { FC } from 'react'; import { useTranslation } from 'react-i18next'; -import { CommonProps, Slots } from '@/shared/types'; +import type { CommonProps, Slots } from '@/shared/types'; -export interface TemplateInvitationListItemProps +type InvitationSlots = 'actions' | 'userAvatar'; +type RequiredInvitationSlots = Extract; + +export interface InvitationListItemTemplateProps extends CommonProps, Omit { - readonly slots: Required> & - Slots<'actions' | 'userAvatar'>; + readonly slots: Slots; readonly inviterName: string; readonly username: string; } -export const TemplateInvitationListItem: FC = ( +export const InvitationListItemTemplate: FC = ( props ) => { const { slots, inviterName, username, ...rest } = props; @@ -36,7 +38,6 @@ export const TemplateInvitationListItem: FC = ( {userAvatar} - {actionsItem} ); diff --git a/src/entities/invitations/ui/skeleton-invitation-card/index.ts b/src/entities/invitations/ui/skeleton-invitation-card/index.ts deleted file mode 100644 index 70cb8af8..00000000 --- a/src/entities/invitations/ui/skeleton-invitation-card/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { SkeletonInvitationCard, type SkeletonInvitationCardProps } from './ui'; diff --git a/src/entities/invitations/ui/skeleton-invitation-card/ui.tsx b/src/entities/invitations/ui/skeleton-invitation-card/ui.tsx deleted file mode 100644 index fab49578..00000000 --- a/src/entities/invitations/ui/skeleton-invitation-card/ui.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Avatar, Card, CardContent, CardHeader, Skeleton } from '@mui/material'; -import * as React from 'react'; - -import { CommonProps } from '@/shared/types'; - -export interface SkeletonInvitationCardProps extends CommonProps {} - -export const SkeletonInvitationCard: React.FC = ( - props -) => { - const { className, } = props; - - return ( - - - - - } - title={} - disableTypography - /> - - - - - - - - - - - - ); -}; diff --git a/src/entities/invitations/ui/skeleton-invitation-list-item/index.ts b/src/entities/invitations/ui/skeleton-invitation-list-item/index.ts deleted file mode 100644 index be065a81..00000000 --- a/src/entities/invitations/ui/skeleton-invitation-list-item/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - SkeletonInvitationListItem, - type SkeletonInvitationListItemProps -} from './skeleton-invitation-list-item'; diff --git a/src/entities/invitations/ui/skeleton-invitation-list-item/skeleton-invitation-list-item.tsx b/src/entities/invitations/ui/skeleton-invitation-list-item/skeleton-invitation-list-item.tsx deleted file mode 100644 index 16c68538..00000000 --- a/src/entities/invitations/ui/skeleton-invitation-list-item/skeleton-invitation-list-item.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { - Avatar, - ListItem, - ListItemAvatar, - ListItemProps, - ListItemText, - Skeleton -} from '@mui/material'; -import cn from 'classnames'; -import * as React from 'react'; - -import { CommonProps } from '@/shared/types'; - -import styles from './skeleton-invitation-list-item.module.css'; - -export interface SkeletonInvitationListItemProps - extends CommonProps, - ListItemProps {} - -export const SkeletonInvitationListItem: React.FC< - SkeletonInvitationListItemProps -> = (props) => { - const { - className, - - ...rest - } = props; - - return ( - - - - - - - } - secondary={} - primaryTypographyProps={{ variant: 'subtitle1', component: 'p', }} - /> - - ); -}; diff --git a/src/entities/invitations/ui/template-invitation-card/index.ts b/src/entities/invitations/ui/template-invitation-card/index.ts deleted file mode 100644 index b06d60bd..00000000 --- a/src/entities/invitations/ui/template-invitation-card/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { TemplateInvitationCard, type TemplateInvitationCardProps } from './ui'; diff --git a/src/entities/invitations/ui/template-invitation-list-item/index.ts b/src/entities/invitations/ui/template-invitation-list-item/index.ts deleted file mode 100644 index 444e176c..00000000 --- a/src/entities/invitations/ui/template-invitation-list-item/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - TemplateInvitationListItem, - type TemplateInvitationListItemProps -} from './template-invitation-list-item'; diff --git a/src/entities/rooms/@x/activities.ts b/src/entities/rooms/@x/activities.ts new file mode 100644 index 00000000..a1e19988 --- /dev/null +++ b/src/entities/rooms/@x/activities.ts @@ -0,0 +1 @@ +export { roomModel } from '../models'; diff --git a/src/entities/rooms/@x/tags.ts b/src/entities/rooms/@x/tags.ts new file mode 100644 index 00000000..a1e19988 --- /dev/null +++ b/src/entities/rooms/@x/tags.ts @@ -0,0 +1 @@ +export { roomModel } from '../models'; diff --git a/src/entities/rooms/@x/tasks.ts b/src/entities/rooms/@x/tasks.ts new file mode 100644 index 00000000..a1e19988 --- /dev/null +++ b/src/entities/rooms/@x/tasks.ts @@ -0,0 +1 @@ +export { roomModel } from '../models'; diff --git a/src/entities/rooms/@x/users.ts b/src/entities/rooms/@x/users.ts new file mode 100644 index 00000000..fa44f5e0 --- /dev/null +++ b/src/entities/rooms/@x/users.ts @@ -0,0 +1,2 @@ +export { roomModel } from '../models'; +export type { RoomId } from '../models'; diff --git a/src/entities/rooms/index.ts b/src/entities/rooms/index.ts index 90786007..f988d9ca 100644 --- a/src/entities/rooms/index.ts +++ b/src/entities/rooms/index.ts @@ -1,3 +1,3 @@ -export * from './model'; -export * from './ui'; +export * from './models'; export * from './lib'; +export * from './ui'; diff --git a/src/entities/rooms/lib/index.ts b/src/entities/rooms/lib/index.ts index f1f8998c..8f4284e3 100644 --- a/src/entities/rooms/lib/index.ts +++ b/src/entities/rooms/lib/index.ts @@ -1 +1,3 @@ -export * from './useRooms'; +export * from './use-rooms'; +export * from './use-room'; +export * from './room-scope-provider'; diff --git a/src/entities/rooms/lib/room-scope-provider.tsx b/src/entities/rooms/lib/room-scope-provider.tsx new file mode 100644 index 00000000..a6bba3d3 --- /dev/null +++ b/src/entities/rooms/lib/room-scope-provider.tsx @@ -0,0 +1,20 @@ +import { ScopeProvider } from 'bunshi/react'; +import { FC, PropsWithChildren } from 'react'; + +import { RoomId, roomModel } from '../models'; + +export interface RoomScopeProviderProps extends Required { + readonly roomId: RoomId; +} + +export const RoomScopeProvider: FC = ( + props: RoomScopeProviderProps +) => { + const { children, roomId, } = props; + + return ( + + {children} + + ); +}; diff --git a/src/entities/rooms/lib/use-room.ts b/src/entities/rooms/lib/use-room.ts new file mode 100644 index 00000000..9c9ae222 --- /dev/null +++ b/src/entities/rooms/lib/use-room.ts @@ -0,0 +1,10 @@ +import { useMolecule } from 'bunshi/react'; + +import { roomModel } from '../models'; + +/** + * Use room provided in current scope where the component is mounted + */ +export const useRoom = () => { + return useMolecule(roomModel.Molecule); +}; diff --git a/src/entities/rooms/lib/use-rooms.ts b/src/entities/rooms/lib/use-rooms.ts new file mode 100644 index 00000000..74fa8f7a --- /dev/null +++ b/src/entities/rooms/lib/use-rooms.ts @@ -0,0 +1,7 @@ +import { useMolecule } from 'bunshi/react'; + +import { roomsModel } from '../models'; + +export const useRooms = () => { + return useMolecule(roomsModel.Molecule); +}; diff --git a/src/entities/rooms/lib/useRooms.ts b/src/entities/rooms/lib/useRooms.ts deleted file mode 100644 index 31428b0c..00000000 --- a/src/entities/rooms/lib/useRooms.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useUnit } from 'effector-react'; - -import { roomsModel } from '../model'; - -export const useRooms = () => { - return useUnit(roomsModel.query); -}; diff --git a/src/entities/rooms/model/index.ts b/src/entities/rooms/model/index.ts deleted file mode 100644 index 9ef39ffd..00000000 --- a/src/entities/rooms/model/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as roomsModel from './rooms'; -export * as roomModel from './room'; diff --git a/src/entities/rooms/model/room.ts b/src/entities/rooms/model/room.ts deleted file mode 100644 index 585bae20..00000000 --- a/src/entities/rooms/model/room.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { cache, createQuery } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createEffect } from 'effector'; - -import { Room, roomsApi, room } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { - StandardResponse, - getStandardResponse, - InRoomParams -} from '@/shared/types'; - -const handlerFx = createEffect(roomsApi.getOne); - -export const query = createQuery< - InRoomParams, - StandardResponse, - Error, - StandardResponse, - Room ->({ - effect: handlerFx, - contract: runtypeContract(getStandardResponse(room)), - - mapData: extractData, -}); - -export const $canChange = query.$data.map((room) => room?.canChange ?? false); - -cache(query); diff --git a/src/entities/rooms/model/rooms.ts b/src/entities/rooms/model/rooms.ts deleted file mode 100644 index 9ca5c344..00000000 --- a/src/entities/rooms/model/rooms.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { cache, createQuery, keepFresh } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createEffect } from 'effector'; -import { interval } from 'patronum'; -import { Array } from 'runtypes'; - -import { room, Room, roomsApi } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { StandardResponse, getStandardResponse } from '@/shared/types'; - -const handlerFx = createEffect(roomsApi.getAll); - -export const query = createQuery< - void, - StandardResponse, - Error, - StandardResponse, - Room[] ->({ - initialData: [], - effect: handlerFx, - contract: runtypeContract(getStandardResponse(Array(room))), - - mapData: extractData, -}); - -cache(query); - -keepFresh(query, { - triggers: [interval({ timeout: 5000, })], -}); diff --git a/src/entities/rooms/models/index.ts b/src/entities/rooms/models/index.ts new file mode 100644 index 00000000..3b69c422 --- /dev/null +++ b/src/entities/rooms/models/index.ts @@ -0,0 +1,2 @@ +export * from './room'; +export * from './rooms'; diff --git a/src/entities/rooms/models/room/index.ts b/src/entities/rooms/models/room/index.ts new file mode 100644 index 00000000..dfdc021f --- /dev/null +++ b/src/entities/rooms/models/room/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as roomModel from './model'; diff --git a/src/entities/rooms/models/room/model.spec.ts b/src/entities/rooms/models/room/model.spec.ts new file mode 100644 index 00000000..bb859b8a --- /dev/null +++ b/src/entities/rooms/models/room/model.spec.ts @@ -0,0 +1,124 @@ +import { take } from '@reatom/framework'; +import { getDefaultInjector } from 'bunshi'; +import { beforeEach, describe, expect, test, vi } from 'vitest'; + +import { + TestCtx, + createTestCtx, + defaultRoom, + handlers, + rooms, + server, + waitNextTick +} from '~/test-utils'; + +import { Molecule, Scope } from './model'; +import type { RoomModel } from './types'; + +describe('entities/rooms/models/room/model.ts', () => { + let ctx: TestCtx; + let model: RoomModel; + + const createModel = (roomId = defaultRoom.id) => { + model = getDefaultInjector().get(Molecule, [Scope, roomId]); + }; + + beforeEach(() => { + ctx = createTestCtx(); + }); + + test('should load room by roomId', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.roomAtom); + + expect(ctx.get(model.pendingAtom)).toBeTruthy(); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual(defaultRoom); + expect(ctx.get(model.errorAtom)).toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should save error if room has not been found', async () => { + createModel(); + + server.use(handlers.rooms.error.getOne.notFound); + + const track = ctx.subscribeTrack(model.roomAtom); + + await waitNextTick(); + + expect(track.lastInput()).toBeNull(); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should save error if something went wrong', async () => { + createModel(); + + server.use(handlers.rooms.error.getOne.internalError); + + const track = ctx.subscribeTrack(model.roomAtom); + + await waitNextTick(); + + expect(track.lastInput()).toBeNull(); + await expect(take(ctx, model.errorAtom)).resolves.not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should save error if returned invalid data', async () => { + createModel(); + + server.use(handlers.rooms.error.getOne.invalidData); + + const track = ctx.subscribeTrack(model.roomAtom); + + await waitNextTick(); + + expect(track.lastInput()).toBeNull(); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should refetch query every 5 seconds', async () => { + vi.useFakeTimers(); + + createModel(); + + server.use(handlers.rooms.error.getOne.invalidData); + + const track = ctx.subscribeTrack(model.roomAtom); + + await vi.advanceTimersByTimeAsync(5000); + + expect(track.lastInput()).toBeNull(); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + + await vi.runOnlyPendingTimersAsync(); + vi.useRealTimers(); + }); + + test('should creaet different instance for different room ids', async () => { + createModel(); + + const oldModel = model; + + createModel(rooms[1].id); + + expect(model).not.toBe(oldModel); + }); +}); diff --git a/src/entities/rooms/models/room/model.ts b/src/entities/rooms/models/room/model.ts new file mode 100644 index 00000000..f47663a1 --- /dev/null +++ b/src/entities/rooms/models/room/model.ts @@ -0,0 +1,68 @@ +import { + atom, + reatomResource, + withCache, + withDataAtom, + withErrorAtom, + withRetry +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { createScope, molecule, use } from 'bunshi'; + +import { roomsApi } from '@/shared/api'; +import { constructName, mapStandardResponse, retryQuery } from '@/shared/lib'; + +import { + type Room, + type RoomId, + type RoomModel, + roomResponseSchema +} from './types'; + +export const Scope = createScope(-1); + +const modelName = 'room'; + +const storage = createMemStorage({ name: modelName, }); +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(storage); + +export const Molecule = molecule((): RoomModel => { + const roomId = use(Scope); + + const fetch = reatomResource( + async (ctx) => { + return ctx.schedule(() => { + return roomsApi + .getOne({ roomId, }, { signal: ctx.controller.signal, }) + .then(roomResponseSchema.parseAsync); + }); + }, + constructName(modelName, roomId.toString(), 'fetch') + ).pipe( + withDataAtom(null as Room | null, mapStandardResponse), + withErrorAtom(undefined, { initState: null, }), + withCache({ withPersist, }), + withRetry() + ); + + const { dataAtom: roomAtom, errorAtom, } = fetch; + const pendingAtom = atom( + (ctx) => { + return !!ctx.spy(fetch.pendingAtom); + }, + constructName(modelName, roomId.toString(), 'pendingAtom') + ); + + retryQuery({ + query: fetch, + store: roomAtom, + timeout: 5000, + }); + + return { + errorAtom, + pendingAtom, + roomAtom, + }; +}); diff --git a/src/entities/rooms/models/room/types.ts b/src/entities/rooms/models/room/types.ts new file mode 100644 index 00000000..d2a6b177 --- /dev/null +++ b/src/entities/rooms/models/room/types.ts @@ -0,0 +1,30 @@ +import { Atom } from '@reatom/framework'; +import zod from 'zod'; + +import { userIdSchema } from '@/entities/users/@x/rooms'; + +import { createStandardResponseSchema } from '@/shared/lib'; + +export const roomSchema = zod + .object({ + id: zod.number(), + ownerId: userIdSchema, + name: zod.string(), + description: zod.string(), + /** + * @deprecated. This property will be reworked in new permissions model + */ + canChange: zod.boolean().nullable().optional(), + }) + .readonly(); +export const roomResponseSchema = createStandardResponseSchema(roomSchema); +export const roomIdSchema = roomSchema.unwrap().shape.id; + +export interface Room extends zod.infer {} +export type RoomId = Room['id']; + +export interface RoomModel { + readonly roomAtom: Atom; + readonly errorAtom: Atom; + readonly pendingAtom: Atom; +} diff --git a/src/entities/rooms/models/rooms/index.ts b/src/entities/rooms/models/rooms/index.ts new file mode 100644 index 00000000..4b79690d --- /dev/null +++ b/src/entities/rooms/models/rooms/index.ts @@ -0,0 +1,3 @@ +export * from './types'; +// Should be removed to allowed rooms? +export * as roomsModel from './model'; diff --git a/src/entities/rooms/models/rooms/model.spec.ts b/src/entities/rooms/models/rooms/model.spec.ts new file mode 100644 index 00000000..2afbf6fe --- /dev/null +++ b/src/entities/rooms/models/rooms/model.spec.ts @@ -0,0 +1,196 @@ +import { noop, take } from '@reatom/framework'; +import { getDefaultInjector } from 'bunshi'; +import { beforeEach, describe, expect, test } from 'vitest'; + +import { + type TestCtx, + createTestCtx, + defaultUser, + handlers, + rooms, + server, + waitNextTick +} from '~/test-utils'; + +import type { Room } from '../room'; + +import { Molecule } from './model'; +import type { RoomsModel } from './types'; + +describe('entities/rooms/model/rooms/model.ts', () => { + let ctx: TestCtx; + let model: RoomsModel; + + const createModel = () => { + model = getDefaultInjector().get(Molecule); + }; + + beforeEach(() => { + ctx = createTestCtx(); + }); + + test('should be the same model across creations', () => { + createModel(); + + const oldModel = model; + + createModel(); + + expect(model).toBe(oldModel); + }); + + test('should load rooms', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.roomsAtom); + + expect(ctx.get(model.pendingAtom)).toBeTruthy(); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual(rooms); + expect(ctx.get(model.errorAtom)).toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should set error if something happened', async () => { + createModel(); + + server.use(handlers.rooms.error.getAll.internalError); + + const track = ctx.subscribeTrack(model.roomsAtom); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual([]); + await expect(take(ctx, model.errorAtom)).resolves.not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should not set data if invalid shape have been loaded', async () => { + createModel(); + + server.use(handlers.rooms.error.getAll.invalidData); + + const track = ctx.subscribeTrack(model.roomsAtom); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual([]); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test.todo('should refetch each 5 seconds'); + + test('should keep cache across models', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.roomsAtom); + + await waitNextTick(); + + track.unsubscribe(); + + createModel(); + + expect(ctx.get(model.roomsAtom)).toStrictEqual(rooms); + }); + + test('should refetch', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.roomsAtom); + + await waitNextTick(); + + const promise = model.refetch(ctx).catch(noop); + + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + await promise; + + expect(track.lastInput()).toStrictEqual(rooms); + expect(ctx.get(model.errorAtom)).toBeNull(); + + track.unsubscribe(); + }); + + test('should keep data if refetch was unsuccessful', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.roomsAtom); + + await waitNextTick(); + + server.use(handlers.rooms.error.getAll.invalidData); + + await model.refetch(ctx).catch(noop); + + expect(track.lastInput()).toStrictEqual(rooms); + await expect(take(ctx, model.errorAtom)).resolves.not.toBeNull(); + + track.unsubscribe(); + }); + + test('should add room into list', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.roomsAtom); + + await waitNextTick(); + + const room: Room = { + id: rooms[1].id + 1, + ownerId: defaultUser.id, + name: 'new room', + description: 'description', + canChange: true, + }; + + model.add(ctx, room); + + expect(track.lastInput()).toStrictEqual([...rooms, room]); + + track.unsubscribe(); + }); + + test('should update room in list', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.roomsAtom); + + await waitNextTick(); + + const room: Room = { + ...rooms[1], + name: 'new room', + }; + + model.update(ctx, room); + + expect(track.lastInput()).toStrictEqual(rooms.toSpliced(1, 1, room)); + + track.unsubscribe(); + }); + + test('should remove room from list', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.roomsAtom); + + await waitNextTick(); + + model.remove(ctx, rooms[1].id); + + expect(track.lastInput()).toStrictEqual(rooms.toSpliced(1, 1)); + + track.unsubscribe(); + }); +}); diff --git a/src/entities/rooms/models/rooms/model.ts b/src/entities/rooms/models/rooms/model.ts new file mode 100644 index 00000000..243f8560 --- /dev/null +++ b/src/entities/rooms/models/rooms/model.ts @@ -0,0 +1,130 @@ +/* eslint-disable no-underscore-dangle */ +import { + action, + atom, + reatomResource, + withCache, + withDataAtom, + withErrorAtom, + withRetry +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { molecule } from 'bunshi'; + +import { roomsApi } from '@/shared/api'; +import { constructName, mapStandardResponse, retryQuery } from '@/shared/lib'; + +import { Room, RoomId } from '../room'; + +import { type Rooms, type RoomsModel, roomsResponseSchema } from './types'; + +const modelName = 'rooms'; + +const storage = createMemStorage({ name: modelName, }); +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(storage); + +export const Molecule = molecule((): RoomsModel => { + const fetch = reatomResource( + async (ctx) => { + return ctx.schedule(() => { + return roomsApi + .getAll({ signal: ctx.controller.signal, }) + .then(roomsResponseSchema.parseAsync); + }); + }, + constructName(modelName, 'fetch') + ).pipe( + withDataAtom([] as Rooms, mapStandardResponse), + withErrorAtom(undefined, { initState: null, }), + withRetry(), + withCache({ withPersist, }) + ); + + const add = action( + (ctx, room: Room) => { + const rooms = ctx.get(roomsAtom); + + const roomsWithNewOne = [...rooms, room]; + + storage.snapshotAtom(ctx, (snapshot) => { + return { + ...snapshot, + [fetch.__reatom.name!]: { + ...snapshot[fetch.__reatom.name!], + data: roomsWithNewOne, + }, + }; + }); + + return roomsAtom(ctx, roomsWithNewOne); + }, + constructName(modelName, 'add') + ); + const update = action( + (ctx, room: Room) => { + const rooms = ctx.get(roomsAtom); + + const updatedRooms = rooms.map((oldRoom) => + oldRoom.id === room.id ? room : oldRoom + ); + + storage.snapshotAtom(ctx, (snapshot) => { + return { + ...snapshot, + [fetch.__reatom.name!]: { + ...snapshot[fetch.__reatom.name!], + data: updatedRooms, + }, + }; + }); + + return roomsAtom(ctx, updatedRooms); + }, + constructName(modelName, 'update') + ); + const remove = action( + (ctx, roomId: RoomId) => { + const rooms = ctx.get(roomsAtom); + + const filteredRooms = rooms.filter((room) => room.id !== roomId); + + storage.snapshotAtom(ctx, (snapshot) => { + return { + ...snapshot, + [fetch.__reatom.name!]: { + ...snapshot[fetch.__reatom.name!], + data: filteredRooms, + }, + }; + }); + + return roomsAtom(ctx, filteredRooms); + }, + constructName(modelName, 'remove') + ); + + const pendingAtom = atom( + (ctx) => { + return !!ctx.spy(fetch.pendingAtom); + }, + constructName(modelName, 'pendingAtom') + ); + const { errorAtom, dataAtom: roomsAtom, retry: refetch, } = fetch; + + retryQuery({ + query: fetch, + store: roomsAtom, + timeout: 5000, + }); + + return { + add, + errorAtom, + pendingAtom, + refetch, + remove, + roomsAtom, + update, + }; +}); diff --git a/src/entities/rooms/models/rooms/types.ts b/src/entities/rooms/models/rooms/types.ts new file mode 100644 index 00000000..6a13122e --- /dev/null +++ b/src/entities/rooms/models/rooms/types.ts @@ -0,0 +1,22 @@ +import { Action, Atom } from '@reatom/framework'; +import zod from 'zod'; + +import { createStandardResponseSchema } from '@/shared/lib'; + +import { Room, RoomId, roomSchema } from '../room'; + +export const roomsSchema = zod.array(roomSchema); +export const roomsResponseSchema = createStandardResponseSchema(roomsSchema); + +export type Rooms = zod.infer; + +export interface RoomsModel { + readonly roomsAtom: Atom; + readonly pendingAtom: Atom; + readonly errorAtom: Atom; + readonly refetch: Action; + + readonly add: Action<[room: Room], Rooms>; + readonly update: Action<[room: Room], Rooms>; + readonly remove: Action<[roomId: RoomId], Rooms>; +} diff --git a/src/entities/rooms/ui/index.ts b/src/entities/rooms/ui/index.ts index ea2ec791..a016dc45 100644 --- a/src/entities/rooms/ui/index.ts +++ b/src/entities/rooms/ui/index.ts @@ -1,3 +1,3 @@ -export * from './skeleton-room-card'; -export * from './template-room-card'; +export * from './room-card-skeleton'; +export * from './room-card-template'; export * from './room-list-item'; diff --git a/src/entities/rooms/ui/room-card-skeleton/__snapshots__/room-card-skeleton.spec.tsx.snap b/src/entities/rooms/ui/room-card-skeleton/__snapshots__/room-card-skeleton.spec.tsx.snap new file mode 100644 index 00000000..2ad586e2 --- /dev/null +++ b/src/entities/rooms/ui/room-card-skeleton/__snapshots__/room-card-skeleton.spec.tsx.snap @@ -0,0 +1,44 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/rooms/ui/room-card-skeleton/room-card-skeleton.tsx > should render list item 1`] = ` +
  • + +
    +
    + + + +
    +
    +
    + +
    +
    + +
    +
  • +`; diff --git a/src/entities/rooms/ui/room-card-skeleton/index.ts b/src/entities/rooms/ui/room-card-skeleton/index.ts new file mode 100644 index 00000000..57a8c7ee --- /dev/null +++ b/src/entities/rooms/ui/room-card-skeleton/index.ts @@ -0,0 +1 @@ +export * from './room-card-skeleton'; diff --git a/src/entities/rooms/ui/room-card-skeleton/room-card-skeleton.spec.tsx b/src/entities/rooms/ui/room-card-skeleton/room-card-skeleton.spec.tsx new file mode 100644 index 00000000..8083af29 --- /dev/null +++ b/src/entities/rooms/ui/room-card-skeleton/room-card-skeleton.spec.tsx @@ -0,0 +1,25 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, render } from '~/test-utils'; + +import { RoomCardSkeleton, RoomCardSkeletonProps } from './room-card-skeleton'; + +describe('entities/rooms/ui/room-card-skeleton/room-card-skeleton.tsx', () => { + let wrapper: RenderResult; + + const defaultProps: RoomCardSkeletonProps = { + className: 'classname', + }; + + const createComponent = (props?: Partial) => { + wrapper = render(); + }; + + const findListItem = () => wrapper.getByRole('listitem'); + + test('should render list item', () => { + createComponent(); + + expect(findListItem()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/rooms/ui/room-card-skeleton/room-card-skeleton.tsx b/src/entities/rooms/ui/room-card-skeleton/room-card-skeleton.tsx new file mode 100644 index 00000000..e4510134 --- /dev/null +++ b/src/entities/rooms/ui/room-card-skeleton/room-card-skeleton.tsx @@ -0,0 +1,33 @@ +import { + Card, + CardActions, + CardContent, + CardHeader, + CardProps, + Skeleton +} from '@mui/material'; +import cn from 'classnames'; +import { FC, memo } from 'react'; + +import { CommonProps } from '@/shared/types'; + +import styles from './styles.module.css'; + +export interface RoomCardSkeletonProps extends CommonProps, CardProps<'li'> {} + +export const RoomCardSkeleton: FC = memo((props) => { + const { className, ...rest } = props; + + return ( + + + } animation='wave' /> + + + + + + + + ); +}); diff --git a/src/entities/rooms/ui/skeleton-room-card/skeleton-room-card.module.css b/src/entities/rooms/ui/room-card-skeleton/styles.module.css similarity index 100% rename from src/entities/rooms/ui/skeleton-room-card/skeleton-room-card.module.css rename to src/entities/rooms/ui/room-card-skeleton/styles.module.css diff --git a/src/entities/rooms/ui/skeleton-room-card/skeleton-room-card.module.css.d.ts b/src/entities/rooms/ui/room-card-skeleton/styles.module.css.d.ts similarity index 100% rename from src/entities/rooms/ui/skeleton-room-card/skeleton-room-card.module.css.d.ts rename to src/entities/rooms/ui/room-card-skeleton/styles.module.css.d.ts diff --git a/src/entities/rooms/ui/room-card-template/__snapshots__/room-card-template.spec.tsx.snap b/src/entities/rooms/ui/room-card-template/__snapshots__/room-card-template.spec.tsx.snap new file mode 100644 index 00000000..7215e227 --- /dev/null +++ b/src/entities/rooms/ui/room-card-template/__snapshots__/room-card-template.spec.tsx.snap @@ -0,0 +1,90 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/rooms/ui/room-card-template/room-card-template.tsx > should render card with name and description > without slots 1`] = ` +
  • +
    +
    +
    + + name + +
    +
    +
    +

    + card.description + : + description +

    +
    +
    +
  • +`; + +exports[`entities/rooms/ui/room-card-template/room-card-template.tsx > should render slots > with slots 1`] = ` +
  • +
    +
    +
    + + name + +
    +
    + +
    +
    +
    +

    + card.description + : + description +

    +
    +
    + +
    +
  • +`; diff --git a/src/entities/rooms/ui/room-card-template/index.ts b/src/entities/rooms/ui/room-card-template/index.ts new file mode 100644 index 00000000..6f01755c --- /dev/null +++ b/src/entities/rooms/ui/room-card-template/index.ts @@ -0,0 +1 @@ +export * from './room-card-template'; diff --git a/src/entities/rooms/ui/room-card-template/room-card-template.spec.tsx b/src/entities/rooms/ui/room-card-template/room-card-template.spec.tsx new file mode 100644 index 00000000..55e19f0e --- /dev/null +++ b/src/entities/rooms/ui/room-card-template/room-card-template.spec.tsx @@ -0,0 +1,37 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, defaultRoom, render } from '~/test-utils'; + +import { RoomCardTemplate, RoomCardTemplateProps } from './room-card-template'; + +describe('entities/rooms/ui/room-card-template/room-card-template.tsx', () => { + let wrapper: RenderResult; + + const defaultProps: RoomCardTemplateProps = { + className: 'classname', + room: defaultRoom, + }; + + const createComponent = (props?: Partial) => { + wrapper = render(); + }; + + const findCard = () => wrapper.getByRole('listitem'); + + test('should render card with name and description', () => { + createComponent(); + + expect(findCard()).toMatchSnapshot('without slots'); + }); + + test('should render slots', () => { + createComponent({ + slots: { + 'footer-actions': , + 'header-action': , + }, + }); + + expect(findCard()).toMatchSnapshot('with slots'); + }); +}); diff --git a/src/entities/rooms/ui/room-card-template/room-card-template.tsx b/src/entities/rooms/ui/room-card-template/room-card-template.tsx new file mode 100644 index 00000000..cdce9091 --- /dev/null +++ b/src/entities/rooms/ui/room-card-template/room-card-template.tsx @@ -0,0 +1,57 @@ +import { + Card, + CardActions, + CardContent, + CardHeader, + CardMedia, + CardProps, + Typography +} from '@mui/material'; +import cn from 'classnames'; +import * as React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { stringToColor } from '@/shared/lib'; +import { CommonProps, Slots } from '@/shared/types'; + +import { Room } from '../../models'; + +import styles from './styles.module.css'; + +type RoomCardSlots = 'header-action' | 'footer-actions'; + +export interface RoomCardTemplateProps extends CommonProps, CardProps<'li'> { + readonly room: Room; + readonly slots?: Slots; +} + +export const RoomCardTemplate: React.FC = (props) => { + const { className, room, slots = {}, ...rest } = props; + + const { t, } = useTranslation('rooms'); + const descriptionT = t('card.description'); + + const sx = { + height: 100, + background: stringToColor(''.padEnd(15, room.id.toString())), + }; + + return ( + + + + + + {descriptionT}: {room.description} + + + + {slots['footer-actions']} + + + ); +}; diff --git a/src/entities/rooms/ui/template-room-card/template-room-card.module.css b/src/entities/rooms/ui/room-card-template/styles.module.css similarity index 99% rename from src/entities/rooms/ui/template-room-card/template-room-card.module.css rename to src/entities/rooms/ui/room-card-template/styles.module.css index 7590e467..99c66325 100644 --- a/src/entities/rooms/ui/template-room-card/template-room-card.module.css +++ b/src/entities/rooms/ui/room-card-template/styles.module.css @@ -18,14 +18,12 @@ } .content { - padding: 1em; - height: max-content; + padding: 1em; } .actions { display: flex; justify-content: flex-end; - padding: 1em; } diff --git a/src/entities/rooms/ui/template-room-card/template-room-card.module.css.d.ts b/src/entities/rooms/ui/room-card-template/styles.module.css.d.ts similarity index 100% rename from src/entities/rooms/ui/template-room-card/template-room-card.module.css.d.ts rename to src/entities/rooms/ui/room-card-template/styles.module.css.d.ts diff --git a/src/entities/rooms/ui/room-list-item/__snapshots__/room-list-item.spec.tsx.snap b/src/entities/rooms/ui/room-list-item/__snapshots__/room-list-item.spec.tsx.snap new file mode 100644 index 00000000..9fe81213 --- /dev/null +++ b/src/entities/rooms/ui/room-list-item/__snapshots__/room-list-item.spec.tsx.snap @@ -0,0 +1,32 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/rooms/ui/room-list-item/room-list-item.tsx > should render list item 1`] = ` +
  • +
    +
    + n +
    +
    +
    + + name + +

    + description +

    +
    +
  • +`; diff --git a/src/entities/rooms/ui/room-list-item/index.ts b/src/entities/rooms/ui/room-list-item/index.ts index 7d362661..46fb9a65 100644 --- a/src/entities/rooms/ui/room-list-item/index.ts +++ b/src/entities/rooms/ui/room-list-item/index.ts @@ -1 +1 @@ -export { RoomListItem, type RoomListItemProps } from './room-list-item'; +export * from './room-list-item'; diff --git a/src/entities/rooms/ui/room-list-item/room-list-item.spec.tsx b/src/entities/rooms/ui/room-list-item/room-list-item.spec.tsx new file mode 100644 index 00000000..725fb1d5 --- /dev/null +++ b/src/entities/rooms/ui/room-list-item/room-list-item.spec.tsx @@ -0,0 +1,26 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, defaultRoom, render } from '~/test-utils'; + +import { RoomListItem, RoomListItemProps } from './room-list-item'; + +describe('entities/rooms/ui/room-list-item/room-list-item.tsx', () => { + let wrapper: RenderResult; + + const defaultProps: RoomListItemProps = { + className: 'classname', + room: defaultRoom, + }; + + const createComponent = (props?: Partial) => { + wrapper = render(); + }; + + const findListItem = () => wrapper.getByRole('listitem'); + + test('should render list item', () => { + createComponent(); + + expect(findListItem()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/rooms/ui/room-list-item/room-list-item.tsx b/src/entities/rooms/ui/room-list-item/room-list-item.tsx index 4712033d..70aa32c0 100644 --- a/src/entities/rooms/ui/room-list-item/room-list-item.tsx +++ b/src/entities/rooms/ui/room-list-item/room-list-item.tsx @@ -2,38 +2,33 @@ import { Avatar, ListItem, ListItemAvatar, - ListItemButton, + ListItemProps, ListItemText } from '@mui/material'; -import { RouteInstance } from 'atomic-router'; -import { Link } from 'atomic-router-react'; import * as React from 'react'; -import { Room } from '@/shared/api'; -import { routes } from '@/shared/configs'; import { stringToColor } from '@/shared/lib'; import { CommonProps } from '@/shared/types'; -export interface RoomListItemProps extends CommonProps, Room {} +import { Room } from '../../models'; + +export interface RoomListItemProps extends CommonProps, ListItemProps { + readonly room: Room; +} export const RoomListItem: React.FC = (props) => { - const { description, id, name, className, } = props; + const { room, className, ...rest } = props; const style = { - background: stringToColor(''.padEnd(15, id.toString())), + background: stringToColor(''.padEnd(15, room.id.toString())), }; return ( - - } - params={{ id, }} - component={Link}> - - {name.at(0)} - - - + + + {room.name.at(0)} + + ); }; diff --git a/src/entities/rooms/ui/skeleton-room-card/index.ts b/src/entities/rooms/ui/skeleton-room-card/index.ts deleted file mode 100644 index 64225ddf..00000000 --- a/src/entities/rooms/ui/skeleton-room-card/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - SkeletonRoomCard, - type SkeletonRoomCardProps -} from './skeleton-room-card'; diff --git a/src/entities/rooms/ui/skeleton-room-card/skeleton-room-card.tsx b/src/entities/rooms/ui/skeleton-room-card/skeleton-room-card.tsx deleted file mode 100644 index e7c77292..00000000 --- a/src/entities/rooms/ui/skeleton-room-card/skeleton-room-card.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { - Card, - CardActions, - CardContent, - CardHeader, - Skeleton -} from '@mui/material'; -import cn from 'classnames'; -import * as React from 'react'; - -import { CommonProps } from '@/shared/types'; - -import styles from './skeleton-room-card.module.css'; - -export interface SkeletonRoomCardProps extends CommonProps {} - -export const SkeletonRoomCard: React.FC = React.memo( - function SkeletonRoomCard(props) { - const { className, } = props; - return ( - - - } animation='wave' /> - - - - - - - - ); - } -); diff --git a/src/entities/rooms/ui/template-room-card/index.ts b/src/entities/rooms/ui/template-room-card/index.ts deleted file mode 100644 index 9f9052ce..00000000 --- a/src/entities/rooms/ui/template-room-card/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - TemplateRoomCard, - type TemplateRoomCardProps -} from './template-room-card'; diff --git a/src/entities/rooms/ui/template-room-card/template-room-card.tsx b/src/entities/rooms/ui/template-room-card/template-room-card.tsx deleted file mode 100644 index 54024500..00000000 --- a/src/entities/rooms/ui/template-room-card/template-room-card.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { - Card, - CardActions, - CardContent, - CardHeader, - CardMedia, - Typography -} from '@mui/material'; -import cn from 'classnames'; -import * as React from 'react'; -import { useTranslation } from 'react-i18next'; - -import { Room } from '@/shared/api'; -import { stringToColor } from '@/shared/lib'; -import { CommonProps } from '@/shared/types'; - -import styles from './template-room-card.module.css'; - -export interface TemplateRoomCardProps extends CommonProps, Room { - readonly menu: React.ReactElement | null; - readonly actions: React.ReactElement | null; -} - -export const TemplateRoomCard: React.FC = (props) => { - const { name, className, description, menu, actions, id, } = props; - const { t, } = useTranslation('rooms'); - const descriptionText = t('card.description'); - - const sx = { - height: 100, - background: stringToColor(''.padEnd(15, id.toString())), - }; - - return ( - - - - - - {descriptionText}: {description} - - - {actions} - - ); -}; diff --git a/src/entities/tags/@x/tasks.ts b/src/entities/tags/@x/tasks.ts new file mode 100644 index 00000000..e5dde83b --- /dev/null +++ b/src/entities/tags/@x/tasks.ts @@ -0,0 +1 @@ +export { tagSchema } from '../models'; diff --git a/src/entities/tags/index.ts b/src/entities/tags/index.ts index 44f2f8c3..f988d9ca 100644 --- a/src/entities/tags/index.ts +++ b/src/entities/tags/index.ts @@ -1,3 +1,3 @@ -export * from './model'; +export * from './models'; export * from './lib'; export * from './ui'; diff --git a/src/entities/tags/lib/use-tag.ts b/src/entities/tags/lib/use-tag.ts new file mode 100644 index 00000000..5f810dee --- /dev/null +++ b/src/entities/tags/lib/use-tag.ts @@ -0,0 +1,7 @@ +import { useMolecule } from 'bunshi/react'; + +import { tagModel } from '../models'; + +export const useTag = () => { + return useMolecule(tagModel.Molecule); +}; diff --git a/src/entities/tags/lib/use-tags.ts b/src/entities/tags/lib/use-tags.ts index 232fd780..74c7ea46 100644 --- a/src/entities/tags/lib/use-tags.ts +++ b/src/entities/tags/lib/use-tags.ts @@ -1,12 +1,7 @@ -import { useUnit } from 'effector-react'; +import { useMolecule } from 'bunshi/react'; -import { tagsModel } from '../model'; +import { tagsModel } from '../models'; export const useTags = () => { - const query = useUnit(tagsModel.query); - const status = useUnit(tagsModel.query.$status); - return { - ...query, - status, - }; + return useMolecule(tagsModel.Molecule); }; diff --git a/src/entities/tags/model/index.ts b/src/entities/tags/model/index.ts deleted file mode 100644 index 5ab6665d..00000000 --- a/src/entities/tags/model/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as tagsModel from './tags'; -export * as tagModel from './tag'; diff --git a/src/entities/tags/model/tag.ts b/src/entities/tags/model/tag.ts deleted file mode 100644 index 4622242a..00000000 --- a/src/entities/tags/model/tag.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createQuery } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createDomain } from 'effector'; - -import { GetTagParams, Tag, tag, tagsApi } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { getStandardResponse, StandardResponse } from '@/shared/types'; - -const tagDomain = createDomain(); - -const handlerFx = tagDomain.effect(tagsApi.getOne); - -export const query = createQuery< - GetTagParams, - StandardResponse, - Error, - StandardResponse, - Tag ->({ - effect: handlerFx, - contract: runtypeContract(getStandardResponse(tag)), - mapData: extractData, -}); diff --git a/src/entities/tags/model/tags.ts b/src/entities/tags/model/tags.ts deleted file mode 100644 index 99a699e7..00000000 --- a/src/entities/tags/model/tags.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { cache, createQuery, keepFresh } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createDomain } from 'effector'; -import { interval } from 'patronum'; -import { Array } from 'runtypes'; - -import { tag, Tag, tagsApi } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { - getStandardResponse, - InRoomParams, - StandardResponse -} from '@/shared/types'; - -export const tagsDomain = createDomain(); - -const handlerFx = tagsDomain.effect(tagsApi.getAll); - -export const query = createQuery< - InRoomParams, - StandardResponse, - Error, - StandardResponse, - Tag[] ->({ - initialData: [], - effect: handlerFx, - contract: runtypeContract(getStandardResponse(Array(tag))), - mapData: extractData, -}); - -cache(query); - -keepFresh(query, { - triggers: [interval({ timeout: 5000, })], -}); diff --git a/src/entities/tags/model/types.ts b/src/entities/tags/model/types.ts deleted file mode 100644 index f3d3bd10..00000000 --- a/src/entities/tags/model/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Tag } from '@/shared/api'; - -export interface TagsMap { - [id: number]: Tag | undefined; -} diff --git a/src/entities/tags/models/index.ts b/src/entities/tags/models/index.ts new file mode 100644 index 00000000..c3eaeb59 --- /dev/null +++ b/src/entities/tags/models/index.ts @@ -0,0 +1,2 @@ +export * from './tags'; +export * from './tag'; diff --git a/src/entities/tags/models/tag/index.ts b/src/entities/tags/models/tag/index.ts new file mode 100644 index 00000000..e88a6f0a --- /dev/null +++ b/src/entities/tags/models/tag/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as tagModel from './model'; diff --git a/src/entities/tags/models/tag/model.spec.ts b/src/entities/tags/models/tag/model.spec.ts new file mode 100644 index 00000000..45576c18 --- /dev/null +++ b/src/entities/tags/models/tag/model.spec.ts @@ -0,0 +1,130 @@ +import { take } from '@reatom/framework'; +import { getDefaultInjector } from 'bunshi'; +import { beforeEach, describe, expect, test, vi } from 'vitest'; + +import { + TestCtx, + createTestCtx, + handlers, + tags, + server, + waitNextTick, + defaultTag +} from '~/test-utils'; + +import { roomModel } from '@/entities/rooms'; + +import { Molecule, Scope } from './model'; +import { TagModel } from './types'; + +describe('entities/tags/models/tag/model.ts', () => { + let ctx: TestCtx; + let model: TagModel; + + const createModel = (tagId = defaultTag.id) => { + model = getDefaultInjector().get( + Molecule, + [roomModel.Scope, defaultTag.roomId], + [Scope, tagId] + ); + }; + + beforeEach(() => { + ctx = createTestCtx(); + }); + + test('should load tag by tagId', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tagAtom); + + expect(ctx.get(model.pendingAtom)).toBeTruthy(); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual(defaultTag); + expect(ctx.get(model.errorAtom)).toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should save error if tag has not been found', async () => { + createModel(); + + server.use(handlers.tags.error.getOne.notFound); + + const track = ctx.subscribeTrack(model.tagAtom); + + await waitNextTick(); + + expect(track.lastInput()).toBeNull(); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should save error if something went wrong', async () => { + createModel(); + + server.use(handlers.tags.error.getOne.internalError); + + const track = ctx.subscribeTrack(model.tagAtom); + + await waitNextTick(); + + expect(track.lastInput()).toBeNull(); + await expect(take(ctx, model.errorAtom)).resolves.not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should save error if returned invalid data', async () => { + createModel(); + + server.use(handlers.tags.error.getOne.invalidData); + + const track = ctx.subscribeTrack(model.tagAtom); + + await waitNextTick(); + + expect(track.lastInput()).toBeNull(); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should refetch query every 5 seconds', async () => { + vi.useFakeTimers(); + + createModel(); + + server.use(handlers.tags.error.getOne.invalidData); + + const track = ctx.subscribeTrack(model.tagAtom); + + await vi.advanceTimersByTimeAsync(5000); + + expect(track.lastInput()).toBeNull(); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + + await vi.runOnlyPendingTimersAsync(); + vi.useRealTimers(); + }); + + test('should creaet different instance for different tag ids', async () => { + createModel(); + + const oldModel = model; + + createModel({ tagId: tags[1].id, }); + + expect(model).not.toBe(oldModel); + }); +}); diff --git a/src/entities/tags/models/tag/model.ts b/src/entities/tags/models/tag/model.ts new file mode 100644 index 00000000..3014ac6c --- /dev/null +++ b/src/entities/tags/models/tag/model.ts @@ -0,0 +1,56 @@ +import { + atom, + reatomResource, + withCache, + withDataAtom, + withErrorAtom +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { createScope, molecule, use } from 'bunshi'; + +import { roomModel } from '@/entities/rooms/@x/tags'; + +import { tagsApi } from '@/shared/api'; +import { constructName, mapStandardResponse } from '@/shared/lib'; + +import { Tag, TagId, TagModel, tagResponseSchema } from './types'; + +export const Scope = createScope(-1); + +const modelName = 'tag'; + +const storage = createMemStorage({ name: modelName, }); +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(storage); + +export const Molecule = molecule((): TagModel => { + const roomId = use(roomModel.Scope); + const tagId = use(Scope); + + const fetch = reatomResource( + async (ctx) => { + return ctx.schedule(() => { + return tagsApi + .getOne({ id: tagId, roomId, }) + .then(tagResponseSchema.parseAsync); + }); + }, + constructName(modelName, roomId, tagId) + ).pipe( + withDataAtom(null as null | Tag, mapStandardResponse), + withErrorAtom(undefined, { initState: null, }), + withCache({ withPersist, }) + ); + + const { dataAtom: tagAtom, errorAtom, } = fetch; + const pendingAtom = atom( + (ctx) => !!ctx.spy(fetch.pendingAtom), + constructName(modelName, 'pendingAtom') + ); + + return { + tagAtom, + errorAtom, + pendingAtom, + }; +}); diff --git a/src/entities/tags/models/tag/types.ts b/src/entities/tags/models/tag/types.ts new file mode 100644 index 00000000..2997baf1 --- /dev/null +++ b/src/entities/tags/models/tag/types.ts @@ -0,0 +1,25 @@ +import { Atom } from '@reatom/framework'; +import zod from 'zod'; + +import { createStandardResponseSchema } from '@/shared/lib'; + +export const tagSchema = zod + .object({ + id: zod.number(), + roomId: zod.number(), + name: zod.string(), + mainColor: zod.string(), + secondColor: zod.string(), + }) + .readonly(); + +export const tagResponseSchema = createStandardResponseSchema(tagSchema); + +export type Tag = zod.infer; +export type TagId = Tag['id']; + +export interface TagModel { + readonly tagAtom: Atom; + readonly errorAtom: Atom; + readonly pendingAtom: Atom; +} diff --git a/src/entities/tags/models/tags/index.ts b/src/entities/tags/models/tags/index.ts new file mode 100644 index 00000000..4470ae24 --- /dev/null +++ b/src/entities/tags/models/tags/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as tagsModel from './model'; diff --git a/src/entities/tags/models/tags/model.spec.ts b/src/entities/tags/models/tags/model.spec.ts new file mode 100644 index 00000000..53bcfb8e --- /dev/null +++ b/src/entities/tags/models/tags/model.spec.ts @@ -0,0 +1,204 @@ +import { noop, take } from '@reatom/framework'; +import { getDefaultInjector } from 'bunshi'; +import { beforeEach, describe, expect, test } from 'vitest'; + +import { + type TestCtx, + createTestCtx, + handlers, + tags, + server, + waitNextTick, + defaultRoom +} from '~/test-utils'; + +// eslint-disable-next-line no-restricted-imports +import { roomModel } from '@/entities/rooms/@x/tags'; + +import type { Tag } from '../tag'; + +import { Molecule } from './model'; +import type { TagsModel } from './types'; + +describe('entities/tags/model/tags/model.ts', () => { + let ctx: TestCtx; + let model: TagsModel; + const roomId = defaultRoom.id; + + const createModel = () => { + model = getDefaultInjector().get(Molecule, [roomModel.Scope, roomId]); + }; + + beforeEach(() => { + ctx = createTestCtx(); + }); + + test('should be the same model across creations', () => { + createModel(); + + const oldModel = model; + + createModel(); + + expect(model).toBe(oldModel); + }); + + test('should load tags', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tagsAtom); + + expect(ctx.get(model.pendingAtom)).toBeTruthy(); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual(tags); + expect(ctx.get(model.errorAtom)).toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should set error if something happened', async () => { + createModel(); + + server.use(handlers.tags.error.getAll.internalError); + + const track = ctx.subscribeTrack(model.tagsAtom); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual([]); + await expect(take(ctx, model.errorAtom)).resolves.not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should not set data if invalid shape have been loaded', async () => { + createModel(); + + server.use(handlers.tags.error.getAll.invalidData); + + const track = ctx.subscribeTrack(model.tagsAtom); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual([]); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test.todo('should refetch each 5 seconds'); + + test('should keep cache across models', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tagsAtom); + + await waitNextTick(); + + track.unsubscribe(); + + model = null; + + await waitNextTick(); + + createModel(); + + expect(ctx.get(model.tagsAtom)).toStrictEqual(tags); + }); + + test('should refetch', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tagsAtom); + + await waitNextTick(); + + const promise = model.refetch(ctx).catch(noop); + + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + await promise; + + expect(track.lastInput()).toStrictEqual(tags); + expect(ctx.get(model.errorAtom)).toBeNull(); + + track.unsubscribe(); + }); + + test('should keep data if refetch was unsuccessful', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tagsAtom); + + await waitNextTick(); + + server.use(handlers.tags.error.getAll.invalidData); + + await model.refetch(ctx).catch(noop); + + expect(track.lastInput()).toStrictEqual(tags); + await expect(take(ctx, model.errorAtom)).resolves.not.toBeNull(); + + track.unsubscribe(); + }); + + test('should add tag into list', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tagsAtom); + + await waitNextTick(); + + const tag: Tag = { + id: tags[1].id + 1, + roomId, + name: 'new tag', + mainColor: '#895467', + secondColor: '#895467', + }; + + model.add(ctx, tag); + + expect(track.lastInput()).toStrictEqual([...tags, tag]); + + track.unsubscribe(); + }); + + test('should update tag in list', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tagsAtom); + + await waitNextTick(); + + const tag: Tag = { + ...tags[1], + name: 'new tag', + }; + + model.update(ctx, tag); + + expect(track.lastInput()).toStrictEqual(tags.toSpliced(1, 1, tag)); + + track.unsubscribe(); + }); + + test('should remove tag from list', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tagsAtom); + + await waitNextTick(); + + model.remove(ctx, tags[1].id); + + expect(track.lastInput()).toStrictEqual(tags.toSpliced(1, 1)); + + track.unsubscribe(); + }); +}); diff --git a/src/entities/tags/models/tags/model.ts b/src/entities/tags/models/tags/model.ts new file mode 100644 index 00000000..3bb3d5b3 --- /dev/null +++ b/src/entities/tags/models/tags/model.ts @@ -0,0 +1,134 @@ +/* eslint-disable no-underscore-dangle */ +import { + reatomResource, + withDataAtom, + withErrorAtom, + withRetry, + withCache, + action, + atom +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { molecule, use } from 'bunshi'; + +import { roomModel } from '@/entities/rooms/@x/tags'; + +import { tagsApi } from '@/shared/api'; +import { constructName, mapStandardResponse, retryQuery } from '@/shared/lib'; + +import { Tag, TagId } from '../tag'; + +import { Tags, TagsModel, tagsResponseSchema } from './types'; + +const modelName = 'tags'; + +const storage = createMemStorage({ name: modelName, }); +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(storage); + +export const Molecule = molecule((): TagsModel => { + const roomId = use(roomModel.Scope); + + const fetch = reatomResource( + async (ctx) => { + return ctx.schedule(() => { + return tagsApi + .getAll({ roomId, }, { signal: ctx.controller.signal, }) + .then(tagsResponseSchema.parseAsync); + }); + }, + constructName(modelName, 'fetch') + ).pipe( + withDataAtom([] as Tags, mapStandardResponse), + withErrorAtom(undefined, { initState: null, }), + withRetry(), + withCache({ withPersist, }) + ); + + const add = action( + (ctx, tag: Tag) => { + const tags = ctx.get(tagsAtom); + + const tagsWithNewOne = [...tags, tag]; + + storage.snapshotAtom(ctx, (snapshot) => { + return { + ...snapshot, + [fetch.__reatom.name!]: { + ...snapshot[fetch.__reatom.name!], + data: tagsWithNewOne, + }, + }; + }); + + return tagsAtom(ctx, tagsWithNewOne); + }, + constructName(modelName, 'add') + ); + const update = action( + (ctx, tag: Tag) => { + const tags = ctx.get(tagsAtom); + + const updatedTags = tags.map((oldTag) => + oldTag.id === tag.id ? tag : oldTag + ); + + storage.snapshotAtom(ctx, (snapshot) => { + return { + ...snapshot, + [fetch.__reatom.name!]: { + ...snapshot[fetch.__reatom.name!], + data: updatedTags, + }, + }; + }); + + return tagsAtom(ctx, updatedTags); + }, + constructName(modelName, 'update') + ); + const remove = action( + (ctx, tagId: TagId) => { + const tags = ctx.get(tagsAtom); + + const filteredTags = tags.filter((tag) => tag.id !== tagId); + + storage.snapshotAtom(ctx, (snapshot) => { + return { + ...snapshot, + [fetch.__reatom.name!]: { + ...snapshot[fetch.__reatom.name!], + data: filteredTags, + }, + }; + }); + + return tagsAtom(ctx, filteredTags); + }, + constructName(modelName, 'remove') + ); + + const pendingAtom = atom( + (ctx) => { + return !!ctx.spy(fetch.pendingAtom); + }, + constructName(modelName, 'pendingAtom') + ); + const { errorAtom, dataAtom: tagsAtom, retry: refetch, } = fetch; + + retryQuery({ + query: fetch, + store: tagsAtom, + timeout: 5000, + }); + + return { + add, + errorAtom, + pendingAtom, + refetch, + remove, + tagsAtom, + update, + }; +}); diff --git a/src/entities/tags/models/tags/types.ts b/src/entities/tags/models/tags/types.ts new file mode 100644 index 00000000..c6839afc --- /dev/null +++ b/src/entities/tags/models/tags/types.ts @@ -0,0 +1,23 @@ +import { Action, Atom } from '@reatom/framework'; +import zod from 'zod'; + +import { createStandardResponseSchema } from '@/shared/lib'; + +import { Tag, TagId, tagSchema } from '../tag'; + +export const tagsSchema = zod.array(tagSchema).readonly(); +export const tagsResponseSchema = createStandardResponseSchema(tagsSchema); + +export type Tags = zod.infer; + +export interface TagsModel { + readonly tagsAtom: Atom; + + readonly pendingAtom: Atom; + readonly errorAtom: Atom; + readonly refetch: Action; + + readonly add: Action<[tag: Tag], Tags>; + readonly update: Action<[tag: Tag], Tags>; + readonly remove: Action<[tagId: TagId], Tags>; +} diff --git a/src/entities/tags/ui/index.ts b/src/entities/tags/ui/index.ts index f4a13faa..c8d43cc6 100644 --- a/src/entities/tags/ui/index.ts +++ b/src/entities/tags/ui/index.ts @@ -1,5 +1,5 @@ export * from './tag-label'; -export * from './skeleton-tag-label'; +export * from './tag-label-skeleton'; export * from './tag-picker'; -export * from './template-tag-list-item'; -export * from './skeleton-tag-list-item'; +export * from './tag-list-item-template'; +export * from './tag-list-item-skeleton'; diff --git a/src/entities/tags/ui/skeleton-tag-label/index.ts b/src/entities/tags/ui/skeleton-tag-label/index.ts deleted file mode 100644 index fb37592d..00000000 --- a/src/entities/tags/ui/skeleton-tag-label/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - SkeletonTagLabel, - type SkeletonTagLabelProps -} from './skeleton-tag-label'; diff --git a/src/entities/tags/ui/skeleton-tag-label/skeleton-tag-label.tsx b/src/entities/tags/ui/skeleton-tag-label/skeleton-tag-label.tsx deleted file mode 100644 index 0c283e88..00000000 --- a/src/entities/tags/ui/skeleton-tag-label/skeleton-tag-label.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Skeleton } from '@mui/material'; -import * as React from 'react'; - -import { CommonProps } from '@/shared/types'; - -export interface SkeletonTagLabelProps extends CommonProps {} - -export const SkeletonTagLabel: React.FC = React.memo( - function SkeletonTagLabel(props) { - const { className, } = props; - return ; - } -); diff --git a/src/entities/tags/ui/skeleton-tag-list-item/index.ts b/src/entities/tags/ui/skeleton-tag-list-item/index.ts deleted file mode 100644 index f1483e0a..00000000 --- a/src/entities/tags/ui/skeleton-tag-list-item/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - SkeletonTagListItem, - type SkeletonTagListItemProps -} from './skeleton-tag-list-item'; diff --git a/src/entities/tags/ui/tag-label-skeleton/__snapshots__/tag-label-skeleton.spec.tsx.snap b/src/entities/tags/ui/tag-label-skeleton/__snapshots__/tag-label-skeleton.spec.tsx.snap new file mode 100644 index 00000000..ab3875bf --- /dev/null +++ b/src/entities/tags/ui/tag-label-skeleton/__snapshots__/tag-label-skeleton.spec.tsx.snap @@ -0,0 +1,8 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/tags/ui/tag-label-skeleton/tag-label-skeleton.tsx > should render correctly 1`] = ` + +`; diff --git a/src/entities/tags/ui/tag-label-skeleton/index.ts b/src/entities/tags/ui/tag-label-skeleton/index.ts new file mode 100644 index 00000000..bb96f6ab --- /dev/null +++ b/src/entities/tags/ui/tag-label-skeleton/index.ts @@ -0,0 +1 @@ +export * from './tag-label-skeleton'; diff --git a/src/entities/tags/ui/tag-label-skeleton/tag-label-skeleton.spec.tsx b/src/entities/tags/ui/tag-label-skeleton/tag-label-skeleton.spec.tsx new file mode 100644 index 00000000..d1133bb5 --- /dev/null +++ b/src/entities/tags/ui/tag-label-skeleton/tag-label-skeleton.spec.tsx @@ -0,0 +1,21 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, render } from '~/test-utils'; + +import { TagLabelSkeleton } from './tag-label-skeleton'; + +describe('entities/tags/ui/tag-label-skeleton/tag-label-skeleton.tsx', () => { + let wrapper: RenderResult; + + const createComponent = () => { + wrapper = render(); + }; + + const findSkeleton = () => wrapper.container.querySelector('span')!; + + test('should render correctly', () => { + createComponent(); + + expect(findSkeleton()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/tags/ui/tag-label-skeleton/tag-label-skeleton.tsx b/src/entities/tags/ui/tag-label-skeleton/tag-label-skeleton.tsx new file mode 100644 index 00000000..01a7a1bd --- /dev/null +++ b/src/entities/tags/ui/tag-label-skeleton/tag-label-skeleton.tsx @@ -0,0 +1,16 @@ +import { Skeleton } from '@mui/material'; +import { ComponentProps, FC, memo } from 'react'; + +import { CommonProps } from '@/shared/types'; + +export interface TagLabelSkeletonProps + extends CommonProps, + ComponentProps<'span'> {} + +export const TagLabelSkeleton: FC = memo((props) => { + const { className, ...rest } = props; + + return ( + + ); +}); diff --git a/src/entities/tags/ui/tag-label/__snapshots__/tag-label.spec.tsx.snap b/src/entities/tags/ui/tag-label/__snapshots__/tag-label.spec.tsx.snap new file mode 100644 index 00000000..9245b315 --- /dev/null +++ b/src/entities/tags/ui/tag-label/__snapshots__/tag-label.spec.tsx.snap @@ -0,0 +1,9 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/tags/ui/tag-label/tag-label.tsx > renders correctly 1`] = ` + + A tag + +`; diff --git a/src/entities/tags/ui/tag-label/index.ts b/src/entities/tags/ui/tag-label/index.ts index 4fb28bbe..29a8134e 100644 --- a/src/entities/tags/ui/tag-label/index.ts +++ b/src/entities/tags/ui/tag-label/index.ts @@ -1 +1 @@ -export { TagLabel, type TagProps } from './tag-label'; +export * from './tag-label'; diff --git a/src/entities/tags/ui/tag-label/tag-label.module.css b/src/entities/tags/ui/tag-label/styles.module.css similarity index 99% rename from src/entities/tags/ui/tag-label/tag-label.module.css rename to src/entities/tags/ui/tag-label/styles.module.css index 8a5bea5d..60a6f583 100644 --- a/src/entities/tags/ui/tag-label/tag-label.module.css +++ b/src/entities/tags/ui/tag-label/styles.module.css @@ -2,11 +2,10 @@ display: inline-block; width: max-content; - padding: 2px 12px; - border-radius: 1.5rem; - - word-wrap: break-word; word-break: break-all; + word-wrap: break-word; + + border-radius: 1.5rem; } diff --git a/src/entities/tags/ui/tag-label/tag-label.module.css.d.ts b/src/entities/tags/ui/tag-label/styles.module.css.d.ts similarity index 100% rename from src/entities/tags/ui/tag-label/tag-label.module.css.d.ts rename to src/entities/tags/ui/tag-label/styles.module.css.d.ts diff --git a/src/entities/tags/ui/tag-label/tag-label.spec.tsx b/src/entities/tags/ui/tag-label/tag-label.spec.tsx new file mode 100644 index 00000000..cdf3f3f1 --- /dev/null +++ b/src/entities/tags/ui/tag-label/tag-label.spec.tsx @@ -0,0 +1,27 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, defaultTag, render } from '~/test-utils'; + +import { TagLabel } from './tag-label'; + +describe('entities/tags/ui/tag-label/tag-label.tsx', () => { + let wrapper: RenderResult; + + const createComponent = () => { + wrapper = render( + + ); + }; + + const findLabel = () => wrapper.getByText(defaultTag.name); + + test('renders correctly', () => { + createComponent(); + + expect(findLabel()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/tags/ui/tag-label/tag-label.tsx b/src/entities/tags/ui/tag-label/tag-label.tsx index f46a7ee1..9a12d10a 100644 --- a/src/entities/tags/ui/tag-label/tag-label.tsx +++ b/src/entities/tags/ui/tag-label/tag-label.tsx @@ -1,25 +1,33 @@ import { SxProps, Typography } from '@mui/material'; import cn from 'classnames'; -import * as React from 'react'; +import { ComponentProps, FC, memo } from 'react'; -import { Tag } from '@/shared/api'; import { CommonProps } from '@/shared/types'; -import styles from './tag-label.module.css'; +import { Tag } from '../../models'; -export interface TagProps extends CommonProps, Omit {} +import styles from './styles.module.css'; + +export interface TagLabelProps + extends CommonProps, + Pick, + Omit, 'color' | 'backgroundColor' | 'id'> {} + +export const TagLabel: FC = memo((props) => { + const { className, mainColor, name, secondColor, ...rest } = props; -export const TagLabel: React.FC = React.memo(function TagLabel( - props -) { - const { className, mainColor, name, secondColor, } = props; const sx: SxProps = { backgroundColor: secondColor, color: mainColor, }; return ( - + {name} ); diff --git a/src/entities/tags/ui/tag-list-item-skeleton/__snapshots__/tag-list-item-skeleton.spec.tsx.snap b/src/entities/tags/ui/tag-list-item-skeleton/__snapshots__/tag-list-item-skeleton.spec.tsx.snap new file mode 100644 index 00000000..b1123c41 --- /dev/null +++ b/src/entities/tags/ui/tag-list-item-skeleton/__snapshots__/tag-list-item-skeleton.spec.tsx.snap @@ -0,0 +1,12 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/tags/ui/tag-list-item-skeleton/tag-list-item-skeleton.tsx > should render without slot > without slot 1`] = ` +
  • + +
  • +`; diff --git a/src/entities/tags/ui/tag-list-item-skeleton/index.ts b/src/entities/tags/ui/tag-list-item-skeleton/index.ts new file mode 100644 index 00000000..e660060e --- /dev/null +++ b/src/entities/tags/ui/tag-list-item-skeleton/index.ts @@ -0,0 +1 @@ +export * from './tag-list-item-skeleton'; diff --git a/src/entities/tags/ui/tag-list-item-skeleton/tag-list-item-skeleton.spec.tsx b/src/entities/tags/ui/tag-list-item-skeleton/tag-list-item-skeleton.spec.tsx new file mode 100644 index 00000000..a74b8a51 --- /dev/null +++ b/src/entities/tags/ui/tag-list-item-skeleton/tag-list-item-skeleton.spec.tsx @@ -0,0 +1,23 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, render } from '~/test-utils'; + +import { TagListItemSkeleton } from './tag-list-item-skeleton'; + +describe('entities/tags/ui/tag-list-item-skeleton/tag-list-item-skeleton.tsx', () => { + let wrapper: RenderResult; + + const createComponent = () => { + wrapper = render(, { + wrapper: ({ children, }) =>
      {children}
    , + }); + }; + + const findListItem = () => wrapper.getByRole('listitem'); + + test('should render without slot', () => { + createComponent(); + + expect(findListItem()).toMatchSnapshot('without slot'); + }); +}); diff --git a/src/entities/tags/ui/skeleton-tag-list-item/skeleton-tag-list-item.tsx b/src/entities/tags/ui/tag-list-item-skeleton/tag-list-item-skeleton.tsx similarity index 57% rename from src/entities/tags/ui/skeleton-tag-list-item/skeleton-tag-list-item.tsx rename to src/entities/tags/ui/tag-list-item-skeleton/tag-list-item-skeleton.tsx index 7b6d70ad..dc6245c9 100644 --- a/src/entities/tags/ui/skeleton-tag-list-item/skeleton-tag-list-item.tsx +++ b/src/entities/tags/ui/tag-list-item-skeleton/tag-list-item-skeleton.tsx @@ -1,16 +1,17 @@ import { ListItem, ListItemProps, Skeleton } from '@mui/material'; -import * as React from 'react'; +import { FC, memo } from 'react'; import { CommonProps } from '@/shared/types'; -export interface SkeletonTagListItemProps extends CommonProps, ListItemProps {} +export interface TagListItemSkeletonProps extends CommonProps, ListItemProps {} -export const SkeletonTagListItem: React.FC = - React.memo(function SkeletonTagLabel(props) { +export const TagListItemSkeleton: FC = memo( + (props) => { const { className, ...rest } = props; return ( ); - }); + } +); diff --git a/src/entities/tags/ui/tag-list-item-template/__snapshots__/tag-list-item-template.spec.tsx.snap b/src/entities/tags/ui/tag-list-item-template/__snapshots__/tag-list-item-template.spec.tsx.snap new file mode 100644 index 00000000..2d33a608 --- /dev/null +++ b/src/entities/tags/ui/tag-list-item-template/__snapshots__/tag-list-item-template.spec.tsx.snap @@ -0,0 +1,54 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`entities/tags/ui/tag-list-item-template/tag-list-item-template.tsx > should render with slot > with slot 1`] = ` +
  • +
    +
    + + + A tag + + +
    +
    +
    + +
    +
  • +`; + +exports[`entities/tags/ui/tag-list-item-template/tag-list-item-template.tsx > should render without slot > without slot 1`] = ` +
  • +
    + + + A tag + + +
    +
  • +`; diff --git a/src/entities/tags/ui/tag-list-item-template/index.ts b/src/entities/tags/ui/tag-list-item-template/index.ts new file mode 100644 index 00000000..7be0705e --- /dev/null +++ b/src/entities/tags/ui/tag-list-item-template/index.ts @@ -0,0 +1 @@ +export * from './tag-list-item-template'; diff --git a/src/entities/tags/ui/tag-list-item-template/tag-list-item-template.spec.tsx b/src/entities/tags/ui/tag-list-item-template/tag-list-item-template.spec.tsx new file mode 100644 index 00000000..c49c0be2 --- /dev/null +++ b/src/entities/tags/ui/tag-list-item-template/tag-list-item-template.spec.tsx @@ -0,0 +1,40 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, render, defaultTag } from '~/test-utils'; + +import { + TagListItemTemplate, + TagListItemTemplateProps +} from './tag-list-item-template'; + +describe('entities/tags/ui/tag-list-item-template/tag-list-item-template.tsx', () => { + let wrapper: RenderResult; + + const defaultProps: TagListItemTemplateProps = { + mainColor: defaultTag.mainColor, + name: defaultTag.name, + secondColor: defaultTag.secondColor, + }; + + const createComponent = (props?: Partial) => { + wrapper = render(, { + wrapper: ({ children, }) =>
      {children}
    , + }); + }; + + const findListItem = () => wrapper.getByRole('listitem'); + + test('should render without slot', () => { + createComponent(); + + expect(findListItem()).toMatchSnapshot('without slot'); + }); + + test('should render with slot', () => { + createComponent({ + slots: { actions: , }, + }); + + expect(findListItem()).toMatchSnapshot('with slot'); + }); +}); diff --git a/src/entities/tags/ui/template-tag-list-item/template-tag-list-item.tsx b/src/entities/tags/ui/tag-list-item-template/tag-list-item-template.tsx similarity index 64% rename from src/entities/tags/ui/template-tag-list-item/template-tag-list-item.tsx rename to src/entities/tags/ui/tag-list-item-template/tag-list-item-template.tsx index f19fef23..1e2698d9 100644 --- a/src/entities/tags/ui/template-tag-list-item/template-tag-list-item.tsx +++ b/src/entities/tags/ui/tag-list-item-template/tag-list-item-template.tsx @@ -7,30 +7,24 @@ import { } from '@mui/material'; import * as React from 'react'; -import { Tag } from '@/shared/api'; import { CommonProps, Slots } from '@/shared/types'; +import { Tag } from '../../models'; import { TagLabel } from '../tag-label'; -export interface TemplateTagListItemProps +type TagListItemTemplateSlots = 'actions'; + +export interface TagListItemTemplateProps extends CommonProps, - Tag, + Pick, Omit { - readonly slots?: Slots<'actions'>; + readonly slots?: Slots; } -export const TemplateTagListItem: React.FC = ( +export const TagListItemTemplate: React.FC = ( props ) => { - const { - id: _, - mainColor, - secondColor, - name, - className, - slots, - ...rest - } = props; + const { mainColor, secondColor, name, className, slots, ...rest } = props; return ( diff --git a/src/entities/tags/ui/tag-picker/index.ts b/src/entities/tags/ui/tag-picker/index.ts index 70d90376..41fc84b2 100644 --- a/src/entities/tags/ui/tag-picker/index.ts +++ b/src/entities/tags/ui/tag-picker/index.ts @@ -1 +1 @@ -export { TagPicker, type TagPickerProps } from './tag-picker'; +export * from './tag-picker'; diff --git a/src/entities/tags/ui/tag-picker/tag-picker.tsx b/src/entities/tags/ui/tag-picker/tag-picker.tsx index 1e46c33f..838384c3 100644 --- a/src/entities/tags/ui/tag-picker/tag-picker.tsx +++ b/src/entities/tags/ui/tag-picker/tag-picker.tsx @@ -1,52 +1,60 @@ -import { Autocomplete, ListItem } from '@mui/material'; -import { useUnit } from 'effector-react'; -import * as React from 'react'; +import { Autocomplete } from '@mui/material'; +import { FC, memo } from 'react'; -import { Tag } from '@/shared/api'; -import { CommonProps, PickerProps } from '@/shared/types'; +import { preparePickerHandler, preparePickerSelectedValue } from '@/shared/lib'; +import { CommonProps, Fn, PickerProps } from '@/shared/types'; import { Field, FieldProps } from '@/shared/ui'; -import { tagsModel } from '../../model'; +import { TagId, Tags } from '../../models'; import { TagLabel } from '../tag-label'; +import { TagListItemTemplate } from '../tag-list-item-template'; export type TagPickerProps = CommonProps & - PickerProps & - Omit; + PickerProps & + Omit & { + readonly onInputChange?: Fn<[value: string], void>; + readonly tags: Tags; + readonly loading?: boolean; + }; -export const TagPicker: React.FC = React.memo((props) => { - const { className, onChange, value, limitTags, multiple, ...rest } = props; - const tags = useUnit(tagsModel.query); +export const TagPicker: FC = memo((props) => { + const { + className, + onChange, + value, + limitTags, + multiple, + tags, + loading, + ...rest + } = props; - let changeHandler; - if (multiple) { - changeHandler = (_: unknown, tags: Tag[]) => { - onChange(tags.map((tag) => tag.id)); - }; - } else { - changeHandler = (_: unknown, tag: Tag | null) => { - onChange(tag?.id || null); - }; - } - - let selected; - if (multiple) { - selected = tags.data.filter((tag) => value.includes(tag.id)); - } else { - selected = tags.data.find((tag) => tag.id === value) ?? null; - } + const handleChange = preparePickerHandler( + { + onChange, + multiple, + }, + 'id' + ); + const selected = preparePickerSelectedValue( + { + value, + multiple, + }, + tags, + 'id' + ); return ( tag.name} renderOption={(props, tag) => ( - - - + )} renderTags={(tags, getTagProps) => { return tags.map((tag, index) => ( diff --git a/src/entities/tags/ui/template-tag-list-item/index.ts b/src/entities/tags/ui/template-tag-list-item/index.ts deleted file mode 100644 index a35083db..00000000 --- a/src/entities/tags/ui/template-tag-list-item/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - TemplateTagListItem, - type TemplateTagListItemProps -} from './template-tag-list-item'; diff --git a/src/entities/tasks/index.ts b/src/entities/tasks/index.ts index 80b33de4..452c4133 100644 --- a/src/entities/tasks/index.ts +++ b/src/entities/tasks/index.ts @@ -1,2 +1,2 @@ -export * from './model'; +export * from './models'; export * from './ui'; diff --git a/src/entities/tasks/lib/index.ts b/src/entities/tasks/lib/index.ts new file mode 100644 index 00000000..ba4c6b6a --- /dev/null +++ b/src/entities/tasks/lib/index.ts @@ -0,0 +1,2 @@ +export * from './use-task'; +export * from './task-scope-provider'; diff --git a/src/entities/tasks/lib/task-scope-provider.tsx b/src/entities/tasks/lib/task-scope-provider.tsx new file mode 100644 index 00000000..7447e7c6 --- /dev/null +++ b/src/entities/tasks/lib/task-scope-provider.tsx @@ -0,0 +1,20 @@ +import { ScopeProvider } from 'bunshi/react'; +import { FC, PropsWithChildren } from 'react'; + +import { TaskId, taskModel } from '../models'; + +export interface TaskScopeProviderProps extends Required { + readonly taskId: TaskId; +} + +export const TaskScopeProvider: FC = ( + props: TaskScopeProviderProps +) => { + const { children, taskId, } = props; + + return ( + + {children} + + ); +}; diff --git a/src/entities/tasks/lib/use-task.ts b/src/entities/tasks/lib/use-task.ts new file mode 100644 index 00000000..47e64402 --- /dev/null +++ b/src/entities/tasks/lib/use-task.ts @@ -0,0 +1,7 @@ +import { useMolecule } from 'bunshi/react'; + +import { taskModel } from '../models'; + +export const useTask = () => { + return useMolecule(taskModel.Molecule); +}; diff --git a/src/entities/tasks/lib/use-tasks.ts b/src/entities/tasks/lib/use-tasks.ts new file mode 100644 index 00000000..a77b1034 --- /dev/null +++ b/src/entities/tasks/lib/use-tasks.ts @@ -0,0 +1,7 @@ +import { useMolecule } from 'bunshi/react'; + +import { tasksModel } from '../models'; + +export const useTasks = () => { + return useMolecule(tasksModel.Molecule); +}; diff --git a/src/entities/tasks/model/index.ts b/src/entities/tasks/model/index.ts deleted file mode 100644 index ab7c4116..00000000 --- a/src/entities/tasks/model/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as tasksInRoomModel from './tasks-in-room'; -export * as taskModel from './task'; diff --git a/src/entities/tasks/model/task.ts b/src/entities/tasks/model/task.ts deleted file mode 100644 index 22e8a7cc..00000000 --- a/src/entities/tasks/model/task.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { createQuery } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createDomain, sample } from 'effector'; -import { createGate } from 'effector-react'; - -import { GetTaskParams, Task, tasksApi, task } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { StandardResponse, getStandardResponse } from '@/shared/types'; - -const taskDomain = createDomain(); - -const handlerFx = taskDomain.effect< - GetTaskParams, - StandardResponse, - Error ->(tasksApi.getOne); - -export const query = createQuery< - GetTaskParams, - StandardResponse, - Error, - StandardResponse, - Task ->({ - effect: handlerFx, - contract: runtypeContract(getStandardResponse(task)), - - mapData: extractData, -}); - -export const Gate = createGate({ - domain: taskDomain, -}); - -sample({ - clock: Gate.open, - target: query.start, -}); - -sample({ - clock: Gate.close, - target: query.reset, -}); diff --git a/src/entities/tasks/model/tasks-in-room.ts b/src/entities/tasks/model/tasks-in-room.ts deleted file mode 100644 index dc52964d..00000000 --- a/src/entities/tasks/model/tasks-in-room.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { cache, createQuery, keepFresh } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { combine, createDomain, sample } from 'effector'; -import { empty, interval, not } from 'patronum'; -import { Array } from 'runtypes'; - -import { Task, tasksApi, task, TaskStatus, GetTasksParams } from '@/shared/api'; -import { createFlag, extractData, group } from '@/shared/lib'; -import { StandardResponse, getStandardResponse } from '@/shared/types'; - -const tasksInRoom = createDomain(); - -const handlerFx = tasksInRoom.effect< - GetTasksParams, - StandardResponse, - Error ->(tasksApi.getAll); - -export const query = createQuery< - GetTasksParams, - StandardResponse, - Error, - StandardResponse, - Task[] ->({ - initialData: [], - effect: handlerFx, - contract: runtypeContract(getStandardResponse(Array(task))), - mapData: extractData, -}); - -export const loaded = createFlag(false); - -sample({ - clock: query.finished.finally, - target: loaded.enable, -}); - -sample({ - clock: query.start, - filter: not(empty(query.$error)), - target: loaded.disable, -}); - -interface Column { - readonly tasks: Task[]; - readonly status: TaskStatus; - readonly hasActions: boolean; -} - -const HAS_ACTIONS: TaskStatus[] = ['ready', 'review', 'in_progress']; - -export const $tasksColumns = combine(query.$data, (tasks) => { - const groupedTasks = group(tasks, 'status'); - - return [ - { - hasActions: HAS_ACTIONS.includes('ready'), - status: 'ready', - tasks: groupedTasks.ready ?? [], - }, - { - hasActions: HAS_ACTIONS.includes('in_progress'), - status: 'in_progress', - tasks: groupedTasks.in_progress ?? [], - }, - { - hasActions: HAS_ACTIONS.includes('review'), - status: 'review', - tasks: groupedTasks.review ?? [], - }, - { - hasActions: HAS_ACTIONS.includes('done'), - status: 'done', - tasks: groupedTasks.done ?? [], - } - ] as Column[]; -}); - -cache(query); - -keepFresh(query, { - triggers: [interval({ timeout: 5000, })], -}); diff --git a/src/entities/tasks/models/index.ts b/src/entities/tasks/models/index.ts new file mode 100644 index 00000000..e07b77ec --- /dev/null +++ b/src/entities/tasks/models/index.ts @@ -0,0 +1,2 @@ +export * from './tasks'; +export * from './task'; diff --git a/src/entities/tasks/models/task/constants.ts b/src/entities/tasks/models/task/constants.ts new file mode 100644 index 00000000..f7db5d30 --- /dev/null +++ b/src/entities/tasks/models/task/constants.ts @@ -0,0 +1,8 @@ +import type { TaskStatus } from './types'; + +export const TASK_STATUSES = { + done: 'done', + inProgress: 'in_progress', + review: 'review', + ready: 'ready', +} satisfies Record; diff --git a/src/entities/tasks/models/task/index.ts b/src/entities/tasks/models/task/index.ts new file mode 100644 index 00000000..76e5895a --- /dev/null +++ b/src/entities/tasks/models/task/index.ts @@ -0,0 +1,3 @@ +export * from './types'; +export * from './constants'; +export * as taskModel from './model'; diff --git a/src/entities/tasks/models/task/model.spec.ts b/src/entities/tasks/models/task/model.spec.ts new file mode 100644 index 00000000..77e69616 --- /dev/null +++ b/src/entities/tasks/models/task/model.spec.ts @@ -0,0 +1,132 @@ +import { take } from '@reatom/framework'; +import { getDefaultInjector } from 'bunshi'; +import { beforeEach, describe, expect, test, vi } from 'vitest'; + +import { + TestCtx, + createTestCtx, + handlers, + tasks, + defaultTask, + server, + waitNextTick, + defaultRoom +} from '~/test-utils'; + +// eslint-disable-next-line no-restricted-imports +import { roomModel } from '@/entities/rooms/@x/tasks'; + +import { Molecule, Scope } from './model'; +import type { TaskModel } from './types'; + +describe('entities/tasks/models/task/model.ts', () => { + let ctx: TestCtx; + let model: TaskModel; + + const createModel = (taskId = defaultTask.id) => { + model = getDefaultInjector().get( + Molecule, + [Scope, taskId], + [roomModel.Scope, defaultRoom.id] + ); + }; + + beforeEach(() => { + ctx = createTestCtx(); + }); + + test('should load task by taskId', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.taskAtom); + + expect(ctx.get(model.pendingAtom)).toBeTruthy(); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual(defaultTask); + expect(ctx.get(model.errorAtom)).toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should save error if task has not been found', async () => { + createModel(); + + server.use(handlers.tasks.error.getOne.notFound); + + const track = ctx.subscribeTrack(model.taskAtom); + + await waitNextTick(); + + expect(track.lastInput()).toBeNull(); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should save error if something went wrong', async () => { + createModel(); + + server.use(handlers.tasks.error.getOne.internalError); + + const track = ctx.subscribeTrack(model.taskAtom); + + await waitNextTick(); + + expect(track.lastInput()).toBeNull(); + await expect(take(ctx, model.errorAtom)).resolves.not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should save error if returned invalid data', async () => { + createModel(); + + server.use(handlers.tasks.error.getOne.invalidData); + + const track = ctx.subscribeTrack(model.taskAtom); + + await waitNextTick(); + + expect(track.lastInput()).toBeNull(); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should refetch query every 5 seconds', async () => { + vi.useFakeTimers(); + + createModel(); + + server.use(handlers.tasks.error.getOne.invalidData); + + const track = ctx.subscribeTrack(model.taskAtom); + + await vi.advanceTimersByTimeAsync(5000); + + expect(track.lastInput()).toBeNull(); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + + await vi.runOnlyPendingTimersAsync(); + vi.useRealTimers(); + }); + + test('should creaet different instance for different task ids', async () => { + createModel(); + + const oldModel = model; + + createModel(tasks[1].id); + + expect(model).not.toBe(oldModel); + }); +}); diff --git a/src/entities/tasks/models/task/model.ts b/src/entities/tasks/models/task/model.ts new file mode 100644 index 00000000..b98a4b11 --- /dev/null +++ b/src/entities/tasks/models/task/model.ts @@ -0,0 +1,63 @@ +import { + atom, + reatomResource, + withCache, + withDataAtom, + withErrorAtom, + withRetry +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { createScope, molecule, use } from 'bunshi'; + +import { roomModel } from '@/entities/rooms/@x/tasks'; + +import { tasksApi } from '@/shared/api'; +import { constructName, mapStandardResponse, retryQuery } from '@/shared/lib'; + +import { taskResponseSchema, type TaskId, type TaskModel, Task } from './types'; + +const modelName = 'task'; + +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(createMemStorage({ name: modelName, })); + +export const Scope = createScope(-1); + +export const Molecule = molecule((): TaskModel => { + const roomId = use(roomModel.Scope); + const id = use(Scope); + + const fetchTask = reatomResource( + (ctx) => { + return ctx.schedule(() => { + return tasksApi + .getOne({ id, roomId, }, { signal: ctx.controller.signal, }) + .then(taskResponseSchema.parseAsync); + }); + }, + constructName(modelName, id, 'fetchTask') + ).pipe( + withDataAtom(null as Task | null, mapStandardResponse), + withErrorAtom(undefined, { initState: null, }), + withRetry(), + withCache({ withPersist, }) + ); + + retryQuery({ + store: fetchTask.dataAtom, + query: fetchTask, + timeout: 5000, + }); + + const { dataAtom: taskAtom, errorAtom, } = fetchTask; + const pendingAtom = atom( + (ctx) => !!ctx.spy(fetchTask.pendingAtom), + constructName(modelName, id, 'pendingAtom') + ); + + return { + taskAtom, + errorAtom, + pendingAtom, + }; +}); diff --git a/src/entities/tasks/models/task/types.ts b/src/entities/tasks/models/task/types.ts new file mode 100644 index 00000000..88135495 --- /dev/null +++ b/src/entities/tasks/models/task/types.ts @@ -0,0 +1,39 @@ +import { Atom } from '@reatom/framework'; +import zod from 'zod'; + +import { tagSchema } from '@/entities/tags/@x/tasks'; +import { userSchema } from '@/entities/users/@x/tasks'; + +import { createStandardResponseSchema } from '@/shared/lib'; + +export const taskStatusSchema = zod.union([ + zod.literal('done'), + zod.literal('in_progress'), + zod.literal('review'), + zod.literal('ready') +]); + +export type TaskStatus = zod.infer; + +export const taskSchema = zod.object({ + id: zod.number(), + roomId: zod.number(), + tags: zod.array(tagSchema), + author: userSchema, + title: zod.string(), + description: zod.string().nullable(), + status: taskStatusSchema, + createdAt: zod.string(), + updatedAt: zod.string().nullable(), +}); + +export const taskResponseSchema = createStandardResponseSchema(taskSchema); + +export interface Task extends zod.infer {} +export type TaskId = Task['id']; + +export interface TaskModel { + readonly taskAtom: Atom; + readonly errorAtom: Atom; + readonly pendingAtom: Atom; +} diff --git a/src/entities/tasks/models/tasks/index.ts b/src/entities/tasks/models/tasks/index.ts new file mode 100644 index 00000000..69d05536 --- /dev/null +++ b/src/entities/tasks/models/tasks/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as tasksModel from './model'; diff --git a/src/entities/tasks/models/tasks/model.spec.ts b/src/entities/tasks/models/tasks/model.spec.ts new file mode 100644 index 00000000..ab87a833 --- /dev/null +++ b/src/entities/tasks/models/tasks/model.spec.ts @@ -0,0 +1,203 @@ +import { noop, take } from '@reatom/framework'; +import { getDefaultInjector } from 'bunshi'; +import { beforeEach, describe, expect, test } from 'vitest'; + +import { + type TestCtx, + createTestCtx, + defaultUser, + handlers, + tasks, + server, + waitNextTick, + defaultRoom +} from '~/test-utils'; + +// eslint-disable-next-line no-restricted-imports +import { roomModel } from '@/entities/rooms/@x/tasks'; + +import type { Task } from '../task'; + +import { Molecule } from './model'; +import type { TasksModel } from './types'; + +describe('entities/tasks/model/tasks/model.ts', () => { + let ctx: TestCtx; + let model: TasksModel; + + const createModel = () => { + model = getDefaultInjector().get(Molecule, [ + roomModel.Scope, + defaultRoom.id + ]); + }; + + beforeEach(() => { + ctx = createTestCtx(); + }); + + test('should be the same model across creations', () => { + createModel(); + + const oldModel = model; + + createModel(); + + expect(model).toBe(oldModel); + }); + + test('should load tasks', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tasksAtom); + + expect(ctx.get(model.pendingAtom)).toBeTruthy(); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual(tasks); + expect(ctx.get(model.errorAtom)).toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should set error if something happened', async () => { + createModel(); + + server.use(handlers.tasks.error.getAll.internalError); + + const track = ctx.subscribeTrack(model.tasksAtom); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual([]); + await expect(take(ctx, model.errorAtom)).resolves.not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test('should not set data if invalid shape have been loaded', async () => { + createModel(); + + server.use(handlers.tasks.error.getAll.invalidData); + + const track = ctx.subscribeTrack(model.tasksAtom); + + await waitNextTick(); + + expect(track.lastInput()).toStrictEqual([]); + expect(ctx.get(model.errorAtom)).not.toBeNull(); + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + track.unsubscribe(); + }); + + test.todo('should refetch each 5 seconds'); + + test('should keep cache across models', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tasksAtom); + + await waitNextTick(); + + track.unsubscribe(); + + createModel(); + + expect(ctx.get(model.tasksAtom)).toStrictEqual(tasks); + }); + + test('should refetch', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tasksAtom); + + await waitNextTick(); + + const promise = model.refetch(ctx).catch(noop); + + expect(ctx.get(model.pendingAtom)).toBeFalsy(); + + await promise; + + expect(track.lastInput()).toStrictEqual(tasks); + expect(ctx.get(model.errorAtom)).toBeNull(); + + track.unsubscribe(); + }); + + test('should keep data if refetch was unsuccessful', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tasksAtom); + + await waitNextTick(); + + server.use(handlers.tasks.error.getAll.invalidData); + + await model.refetch(ctx).catch(noop); + + expect(track.lastInput()).toStrictEqual(tasks); + await expect(take(ctx, model.errorAtom)).resolves.not.toBeNull(); + + track.unsubscribe(); + }); + + test('should add task into list', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tasksAtom); + + await waitNextTick(); + + const task: Task = { + id: tasks[1].id + 1, + ownerId: defaultUser.id, + name: 'new task', + description: 'description', + canChange: true, + }; + + model.add(ctx, task); + + expect(track.lastInput()).toStrictEqual([...tasks, task]); + + track.unsubscribe(); + }); + + test('should update task in list', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tasksAtom); + + await waitNextTick(); + + const task: Task = { + ...tasks[1], + name: 'new task', + }; + + model.update(ctx, task); + + expect(track.lastInput()).toStrictEqual(tasks.toSpliced(1, 1, task)); + + track.unsubscribe(); + }); + + test('should remove task from list', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.tasksAtom); + + await waitNextTick(); + + model.remove(ctx, tasks[1].id); + + expect(track.lastInput()).toStrictEqual(tasks.toSpliced(1, 1)); + + track.unsubscribe(); + }); +}); diff --git a/src/entities/tasks/models/tasks/model.ts b/src/entities/tasks/models/tasks/model.ts new file mode 100644 index 00000000..6289af38 --- /dev/null +++ b/src/entities/tasks/models/tasks/model.ts @@ -0,0 +1,134 @@ +/* eslint-disable no-underscore-dangle */ +import { + action, + atom, + reatomResource, + withCache, + withDataAtom, + withErrorAtom, + withRetry +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { molecule, use } from 'bunshi'; + +import { roomModel } from '@/entities/rooms/@x/tasks'; + +import { tasksApi } from '@/shared/api'; +import { constructName, mapStandardResponse, retryQuery } from '@/shared/lib'; + +import { Task, TaskId } from '../task'; + +import { type Tasks, type TasksModel, tasksResponseSchema } from './types'; + +const modelName = 'tasks'; + +const storage = createMemStorage({ name: modelName, }); +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(storage); + +export const Molecule = molecule((): TasksModel => { + const roomId = use(roomModel.Scope); + + const fetch = reatomResource( + async (ctx) => { + return ctx.schedule(() => { + return tasksApi + .getAll({ roomId, }, { signal: ctx.controller.signal, }) + .then(tasksResponseSchema.parseAsync); + }); + }, + constructName(modelName, 'fetch') + ).pipe( + withDataAtom([] as Tasks, mapStandardResponse), + withErrorAtom(undefined, { initState: null, }), + withRetry(), + withCache({ withPersist, }) + ); + + const add = action( + (ctx, task: Task) => { + const tasks = ctx.get(tasksAtom); + + const tasksWithNewOne = [...tasks, task]; + + storage.snapshotAtom(ctx, (snapshot) => { + return { + ...snapshot, + [fetch.__reatom.name!]: { + ...snapshot[fetch.__reatom.name!], + data: tasksWithNewOne, + }, + }; + }); + + return tasksAtom(ctx, tasksWithNewOne); + }, + constructName(modelName, 'add') + ); + const update = action( + (ctx, task: Task) => { + const tasks = ctx.get(tasksAtom); + + const updatedTasks = tasks.map((oldTask) => + oldTask.id === task.id ? task : oldTask + ); + + storage.snapshotAtom(ctx, (snapshot) => { + return { + ...snapshot, + [fetch.__reatom.name!]: { + ...snapshot[fetch.__reatom.name!], + data: updatedTasks, + }, + }; + }); + + return tasksAtom(ctx, updatedTasks); + }, + constructName(modelName, 'update') + ); + const remove = action( + (ctx, taskId: TaskId) => { + const tasks = ctx.get(tasksAtom); + + const filteredTasks = tasks.filter((task) => task.id !== taskId); + + storage.snapshotAtom(ctx, (snapshot) => { + return { + ...snapshot, + [fetch.__reatom.name!]: { + ...snapshot[fetch.__reatom.name!], + data: filteredTasks, + }, + }; + }); + + return tasksAtom(ctx, filteredTasks); + }, + constructName(modelName, 'remove') + ); + + const pendingAtom = atom( + (ctx) => { + return !!ctx.spy(fetch.pendingAtom); + }, + constructName(modelName, 'pendingAtom') + ); + const { errorAtom, dataAtom: tasksAtom, retry: refetch, } = fetch; + + retryQuery({ + query: fetch, + store: tasksAtom, + timeout: 5000, + }); + + return { + add, + errorAtom, + pendingAtom, + refetch, + remove, + tasksAtom, + update, + }; +}); diff --git a/src/entities/tasks/models/tasks/types.ts b/src/entities/tasks/models/tasks/types.ts new file mode 100644 index 00000000..058d7443 --- /dev/null +++ b/src/entities/tasks/models/tasks/types.ts @@ -0,0 +1,22 @@ +import { Action, Atom } from '@reatom/framework'; +import zod from 'zod'; + +import { createStandardResponseSchema } from '@/shared/lib'; + +import { Task, TaskId, taskSchema } from '../task'; + +export const tasksSchema = zod.array(taskSchema); +export const tasksResponseSchema = createStandardResponseSchema(tasksSchema); + +export type Tasks = zod.infer; + +export interface TasksModel { + readonly tasksAtom: Atom; + readonly pendingAtom: Atom; + readonly errorAtom: Atom; + readonly refetch: Action; + + readonly add: Action<[task: Task], Tasks>; + readonly update: Action<[task: Task], Tasks>; + readonly remove: Action<[taskId: TaskId], Tasks>; +} diff --git a/src/entities/tasks/ui/index.ts b/src/entities/tasks/ui/index.ts index 85656d6c..b077ec44 100644 --- a/src/entities/tasks/ui/index.ts +++ b/src/entities/tasks/ui/index.ts @@ -1,4 +1,4 @@ -export * from './skeleton-task-card'; -export * from './template-task-card'; +export * from './task-card-skeleton'; +export * from './task-card-skeleton'; export * from './task-column-header'; -export * from './status-select'; +export * from './task-status-select'; diff --git a/src/entities/tasks/ui/skeleton-task-card/index.ts b/src/entities/tasks/ui/skeleton-task-card/index.ts deleted file mode 100644 index a0e6c9d8..00000000 --- a/src/entities/tasks/ui/skeleton-task-card/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - SkeletonTaskCard, - type SkeletonTaskCardProps -} from './skeleton-task-card'; diff --git a/src/entities/tasks/ui/skeleton-task-card/skeleton-task-card.tsx b/src/entities/tasks/ui/skeleton-task-card/skeleton-task-card.tsx deleted file mode 100644 index 42cb816a..00000000 --- a/src/entities/tasks/ui/skeleton-task-card/skeleton-task-card.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint-disable react/no-array-index-key */ -import { - Card, - CardContent, - CardHeader, - Skeleton, - Typography -} from '@mui/material'; -import * as React from 'react'; - -import { CommonProps } from '@/shared/types'; - -export interface SkeletonTaskCardProps extends CommonProps { - readonly contentLinesCount?: number; -} - -export const SkeletonTaskCard: React.FC = React.memo( - function SkeletonTaskCard(props) { - const { className, contentLinesCount = 2, } = props; - const lines = Array(contentLinesCount).fill(0); - return ( - - } /> - - {lines.map((_, i) => ( - - - - ))} - - - ); - } -); diff --git a/src/entities/tasks/ui/status-select/index.ts b/src/entities/tasks/ui/status-select/index.ts deleted file mode 100644 index 718385ac..00000000 --- a/src/entities/tasks/ui/status-select/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { StatusSelect, type StatusSelectProps } from './status-select'; diff --git a/src/entities/tasks/ui/task-card-skeleton/__snapshots__/task-card-skeleton.spec.tsx.snap b/src/entities/tasks/ui/task-card-skeleton/__snapshots__/task-card-skeleton.spec.tsx.snap new file mode 100644 index 00000000..a16db05a --- /dev/null +++ b/src/entities/tasks/ui/task-card-skeleton/__snapshots__/task-card-skeleton.spec.tsx.snap @@ -0,0 +1,95 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`TaskCardSkeleton > should render correctly 1`] = ` +
    +
    +
    + + + +
    +
    +
    +

    + +

    +

    + +

    +
    +
    +`; + +exports[`TaskCardSkeleton > should render passed number of lines > custom number of lines 1`] = ` +
    +
    +
    + + + +
    +
    +
    +

    + +

    +

    + +

    +

    + +

    +
    +
    +`; diff --git a/src/entities/tasks/ui/task-card-skeleton/index.ts b/src/entities/tasks/ui/task-card-skeleton/index.ts new file mode 100644 index 00000000..158aca19 --- /dev/null +++ b/src/entities/tasks/ui/task-card-skeleton/index.ts @@ -0,0 +1 @@ +export * from './task-card-skeleton'; diff --git a/src/entities/tasks/ui/task-card-skeleton/task-card-skeleton.spec.tsx b/src/entities/tasks/ui/task-card-skeleton/task-card-skeleton.spec.tsx new file mode 100644 index 00000000..ae12ab89 --- /dev/null +++ b/src/entities/tasks/ui/task-card-skeleton/task-card-skeleton.spec.tsx @@ -0,0 +1,29 @@ +import { describe, test, expect } from 'vitest'; + +import { render, type RenderResult } from '~/test-utils'; + +import { TaskCardSkeleton } from './task-card-skeleton'; + +describe('TaskCardSkeleton', () => { + let wrapper: RenderResult; + + const createComponent = (contentLinesCount?: number) => { + wrapper = render( + + ); + }; + + const findCard = () => wrapper.container.querySelector('div')!; + + test('should render correctly', () => { + createComponent(); + + expect(findCard()).toMatchSnapshot(); + }); + + test('should render passed number of lines', () => { + createComponent(3); + + expect(findCard()).toMatchSnapshot('custom number of lines'); + }); +}); diff --git a/src/entities/tasks/ui/task-card-skeleton/task-card-skeleton.tsx b/src/entities/tasks/ui/task-card-skeleton/task-card-skeleton.tsx new file mode 100644 index 00000000..1a59ab21 --- /dev/null +++ b/src/entities/tasks/ui/task-card-skeleton/task-card-skeleton.tsx @@ -0,0 +1,33 @@ +/* eslint-disable react/no-array-index-key */ +import { + Card, + CardContent, + CardHeader, + CardProps, + Skeleton, + Typography +} from '@mui/material'; +import { type FC, memo } from 'react'; + +import { CommonProps } from '@/shared/types'; + +export interface TaskCardSkeletonProps extends CommonProps, CardProps { + readonly contentLinesCount?: number; +} + +export const TaskCardSkeleton: FC = memo((props) => { + const { className, contentLinesCount = 2, ...rest } = props; + const lines = Array(contentLinesCount).fill(0); + return ( + + } /> + + {lines.map((_, i) => ( + + + + ))} + + + ); +}); diff --git a/src/entities/tasks/ui/task-card-template/__snapshots__/task-card-template.spec.tsx.snap b/src/entities/tasks/ui/task-card-template/__snapshots__/task-card-template.spec.tsx.snap new file mode 100644 index 00000000..608f625f --- /dev/null +++ b/src/entities/tasks/ui/task-card-template/__snapshots__/task-card-template.spec.tsx.snap @@ -0,0 +1,98 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`TaskCardTemplate > should render actions if they are passed > with actions 1`] = ` +
    +
    +
    +

    + Title 1 +

    +
    +
    +
    + Actions +
    +
    +
    +
    +

    + Description 1 +

    +
    +
    + +
    +
    +`; + +exports[`TaskCardTemplate > should render correctly 1`] = ` +
    +
    +
    +

    + Title 1 +

    +
    + Tags +
    +
    +
    +
    +

    + Description 1 +

    +
    +
    +
    + User Avatar +
    + +
    +
    +`; diff --git a/src/entities/tasks/ui/task-card-template/index.ts b/src/entities/tasks/ui/task-card-template/index.ts new file mode 100644 index 00000000..e332d984 --- /dev/null +++ b/src/entities/tasks/ui/task-card-template/index.ts @@ -0,0 +1 @@ +export * from './task-card-template'; diff --git a/src/entities/tasks/ui/template-task-card/template-task-card.module.css b/src/entities/tasks/ui/task-card-template/styles.module.css similarity index 99% rename from src/entities/tasks/ui/template-task-card/template-task-card.module.css rename to src/entities/tasks/ui/task-card-template/styles.module.css index f04f98e4..4f8dbf1a 100644 --- a/src/entities/tasks/ui/template-task-card/template-task-card.module.css +++ b/src/entities/tasks/ui/task-card-template/styles.module.css @@ -1,6 +1,5 @@ .card { width: 100%; - box-shadow: rgba(99, 99, 99, 0.1) 0px 2px 8px 0px; } @@ -27,6 +26,5 @@ .actions { display: flex; justify-content: space-between; - padding: 1em; } diff --git a/src/entities/tasks/ui/template-task-card/template-task-card.module.css.d.ts b/src/entities/tasks/ui/task-card-template/styles.module.css.d.ts similarity index 100% rename from src/entities/tasks/ui/template-task-card/template-task-card.module.css.d.ts rename to src/entities/tasks/ui/task-card-template/styles.module.css.d.ts diff --git a/src/entities/tasks/ui/task-card-template/task-card-template.spec.tsx b/src/entities/tasks/ui/task-card-template/task-card-template.spec.tsx new file mode 100644 index 00000000..0030f0ea --- /dev/null +++ b/src/entities/tasks/ui/task-card-template/task-card-template.spec.tsx @@ -0,0 +1,42 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, defaultTask, render } from '~/test-utils'; + +import { TaskCardTemplate, TaskCardTemplateProps } from './task-card-template'; + +describe('TaskCardTemplate', () => { + let wrapper: RenderResult; + + const defaultProps: TaskCardTemplateProps = { + createdAt: defaultTask.createdAt, + description: defaultTask.description, + title: defaultTask.title, + slots: { + tags:
    Tags
    , + userAvatar:
    User Avatar
    , + }, + }; + + const createComponent = (props: Partial = {}) => { + wrapper = render(); + }; + + const findCard = () => + wrapper.getByRole('article', { name: defaultTask.title, }); + + test('should render correctly', () => { + createComponent(); + + expect(findCard()).toMatchSnapshot(); + }); + + test('should render actions if they are passed', () => { + createComponent({ + slots: { + actions:
    Actions
    , + }, + }); + + expect(findCard()).toMatchSnapshot('with actions'); + }); +}); diff --git a/src/entities/tasks/ui/task-card-template/task-card-template.tsx b/src/entities/tasks/ui/task-card-template/task-card-template.tsx new file mode 100644 index 00000000..9e2857e7 --- /dev/null +++ b/src/entities/tasks/ui/task-card-template/task-card-template.tsx @@ -0,0 +1,63 @@ +import { + Card, + CardActions, + CardContent, + CardHeader, + CardProps, + Typography +} from '@mui/material'; +import cn from 'classnames'; +import { type FC, memo, useId } from 'react'; + +import type { CommonProps, Slots } from '@/shared/types'; +import { DateTime } from '@/shared/ui'; + +import type { Task } from '../../models'; + +import styles from './styles.module.css'; + +type TaskCardSlots = 'actions' | 'tags' | 'userAvatar'; +type RequiredTaskCardSlots = Exclude; + +export interface TaskCardTemplateProps + extends CommonProps, + Pick, + Omit { + readonly slots: Slots; +} + +export const TaskCardTemplate: FC = memo((props) => { + const { className, createdAt, slots, title, description, ...rest } = props; + const id = useId(); + const { actions, tags, userAvatar, } = slots; + + return ( + + + {title} +
    + } + subheader={tags} + disableTypography + /> + + + {description} + + + + {userAvatar} + + + + ); +}); diff --git a/src/entities/tasks/ui/task-column-header/__snapshots__/task-column-header.spec.tsx.snap b/src/entities/tasks/ui/task-column-header/__snapshots__/task-column-header.spec.tsx.snap new file mode 100644 index 00000000..63c489fa --- /dev/null +++ b/src/entities/tasks/ui/task-column-header/__snapshots__/task-column-header.spec.tsx.snap @@ -0,0 +1,32 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`TaskColumnHeader > should render column header 1`] = ` +
    +

    + statuses.done +

    +
    +`; + +exports[`TaskColumnHeader > should render header with passed actions > with actions 1`] = ` +
    +

    + statuses.done +

    +
    + Actions +
    +
    +`; diff --git a/src/entities/tasks/ui/task-column-header/index.ts b/src/entities/tasks/ui/task-column-header/index.ts index 53e42be2..0e36c141 100644 --- a/src/entities/tasks/ui/task-column-header/index.ts +++ b/src/entities/tasks/ui/task-column-header/index.ts @@ -1,4 +1 @@ -export { - TaskColumnHeader, - type TaskColumnHeaderComponent -} from './task-column-header'; +export * from './task-column-header'; diff --git a/src/entities/tasks/ui/task-column-header/task-column-header.module.css b/src/entities/tasks/ui/task-column-header/styles.module.css similarity index 100% rename from src/entities/tasks/ui/task-column-header/task-column-header.module.css rename to src/entities/tasks/ui/task-column-header/styles.module.css diff --git a/src/entities/tasks/ui/task-column-header/task-column-header.module.css.d.ts b/src/entities/tasks/ui/task-column-header/styles.module.css.d.ts similarity index 100% rename from src/entities/tasks/ui/task-column-header/task-column-header.module.css.d.ts rename to src/entities/tasks/ui/task-column-header/styles.module.css.d.ts diff --git a/src/entities/tasks/ui/task-column-header/task-column-header.spec.tsx b/src/entities/tasks/ui/task-column-header/task-column-header.spec.tsx new file mode 100644 index 00000000..9cbd9cb0 --- /dev/null +++ b/src/entities/tasks/ui/task-column-header/task-column-header.spec.tsx @@ -0,0 +1,35 @@ +import { describe, test, expect } from 'vitest'; + +import { defaultTask, render, type RenderResult } from '~/test-utils'; + +import { TaskColumnHeader, TaskColumnHeaderProps } from './task-column-header'; + +describe('TaskColumnHeader', () => { + let wrapper: RenderResult; + + const defaultProps: TaskColumnHeaderProps = { + status: defaultTask.status, + }; + + const createComponent = (props: Partial = {}) => { + wrapper = render(); + }; + + const findHeader = () => wrapper.getByRole('banner'); + + test('should render column header', () => { + createComponent(); + + expect(findHeader()).toMatchSnapshot(); + }); + + test('should render header with passed actions', () => { + createComponent({ + slots: { + actions:
    Actions
    , + }, + }); + + expect(findHeader()).toMatchSnapshot('with actions'); + }); +}); diff --git a/src/entities/tasks/ui/task-column-header/task-column-header.tsx b/src/entities/tasks/ui/task-column-header/task-column-header.tsx index e7043743..dacad316 100644 --- a/src/entities/tasks/ui/task-column-header/task-column-header.tsx +++ b/src/entities/tasks/ui/task-column-header/task-column-header.tsx @@ -1,25 +1,37 @@ import { Typography } from '@mui/material'; import cn from 'classnames'; -import * as React from 'react'; +import { memo, type FC, type ComponentProps, useId } from 'react'; +import { useTranslation } from 'react-i18next'; -import { CommonProps, Slots } from '@/shared/types'; +import type { CommonProps, Slots } from '@/shared/types'; -import styles from './task-column-header.module.css'; +import type { TaskStatus } from '../../models'; -export interface TaskColumnHeaderComponent extends CommonProps { - readonly id?: string; - readonly slots?: Slots<'actions'>; +import styles from './styles.module.css'; + +type TaskColumnSlots = 'actions'; + +export interface TaskColumnHeaderProps + extends CommonProps, + ComponentProps<'header'> { + readonly status: TaskStatus; + readonly slots?: Slots; } -export const TaskColumnHeader: React.FC< - React.PropsWithChildren -> = React.memo((props) => { - const { children, className, slots, id, } = props; +export const TaskColumnHeader: FC = memo((props) => { + const { className, slots, status, ...rest } = props; + const id = useId(); + const { t, } = useTranslation('tasks'); + + const headerT = t(`statuses.${status}`); return ( -
    - - {children} +
    + + {headerT} {slots?.actions}
    diff --git a/src/entities/tasks/ui/task-status-select/__snapshots__/task-status-select.spec.tsx.snap b/src/entities/tasks/ui/task-status-select/__snapshots__/task-status-select.spec.tsx.snap new file mode 100644 index 00000000..07f022ca --- /dev/null +++ b/src/entities/tasks/ui/task-status-select/__snapshots__/task-status-select.spec.tsx.snap @@ -0,0 +1,60 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`TaskStatusSelect > should render correctly 1`] = ` +
    +
    + + + + +
    +
    +`; diff --git a/src/entities/tasks/ui/task-status-select/index.ts b/src/entities/tasks/ui/task-status-select/index.ts new file mode 100644 index 00000000..76c17cfb --- /dev/null +++ b/src/entities/tasks/ui/task-status-select/index.ts @@ -0,0 +1 @@ +export * from './task-status-select'; diff --git a/src/entities/tasks/ui/task-status-select/task-status-select.spec.tsx b/src/entities/tasks/ui/task-status-select/task-status-select.spec.tsx new file mode 100644 index 00000000..9804089c --- /dev/null +++ b/src/entities/tasks/ui/task-status-select/task-status-select.spec.tsx @@ -0,0 +1,25 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, render } from '~/test-utils'; + +import { TaskStatusSelect, TaskStatusSelectProps } from './task-status-select'; + +describe('TaskStatusSelect', () => { + let wrapper: RenderResult; + + const createComponent = (props: TaskStatusSelectProps = {}) => { + wrapper = render(); + }; + + const findRoot = () => wrapper.container.querySelector('div')!; + + test('should render correctly', () => { + createComponent(); + + expect(findRoot()).toMatchSnapshot(); + }); + + test.todo('should allow select one of statuses'); + + test.todo('should allow render empty optino'); +}); diff --git a/src/entities/tasks/ui/status-select/status-select.tsx b/src/entities/tasks/ui/task-status-select/task-status-select.tsx similarity index 73% rename from src/entities/tasks/ui/status-select/status-select.tsx rename to src/entities/tasks/ui/task-status-select/task-status-select.tsx index b54fab29..a8c7be82 100644 --- a/src/entities/tasks/ui/status-select/status-select.tsx +++ b/src/entities/tasks/ui/task-status-select/task-status-select.tsx @@ -1,21 +1,23 @@ import { MenuItem } from '@mui/material'; -import * as React from 'react'; +import { FC, memo } from 'react'; import { useTranslation } from 'react-i18next'; -import { statuses } from '@/shared/api'; import { CommonProps } from '@/shared/types'; import { Field, FieldProps } from '@/shared/ui'; -export interface StatusSelectProps +import { TASK_STATUSES } from '../../models'; + +export interface TaskStatusSelectProps extends CommonProps, Omit { readonly hasEmptyOption?: boolean; readonly emptyOptionText?: string; } -export const StatusSelect: React.FC = React.memo((props) => { +export const TaskStatusSelect: FC = memo((props) => { const { t, } = useTranslation('tasks'); const { hasEmptyOption, emptyOptionText, ...rest } = props; + return ( {hasEmptyOption ? ( @@ -23,7 +25,7 @@ export const StatusSelect: React.FC = React.memo((props) => { {emptyOptionText} ) : null} - {statuses.map((name) => ( + {Object.values(TASK_STATUSES).map((name) => ( {t(`statuses.${name}`)} diff --git a/src/entities/tasks/ui/template-task-card/index.ts b/src/entities/tasks/ui/template-task-card/index.ts deleted file mode 100644 index 05ca51a6..00000000 --- a/src/entities/tasks/ui/template-task-card/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - TemplateTaskCard, - type TemplateTaskCardProps -} from './template-task-card'; diff --git a/src/entities/tasks/ui/template-task-card/template-task-card.tsx b/src/entities/tasks/ui/template-task-card/template-task-card.tsx deleted file mode 100644 index 06d84977..00000000 --- a/src/entities/tasks/ui/template-task-card/template-task-card.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { - Card, - CardActions, - CardContent, - CardHeader, - CardProps, - Typography -} from '@mui/material'; -import cn from 'classnames'; -import * as React from 'react'; - -import { Task } from '@/shared/api'; -import { CommonProps, Slots } from '@/shared/types'; -import { DateTime } from '@/shared/ui'; - -import styles from './template-task-card.module.css'; - -export interface TemplateTaskCardProps - extends CommonProps, - Pick, - Omit { - readonly slots: Slots<'actions' | 'tags' | 'userAvatar'>; -} - -export const TemplateTaskCard: React.FC = React.memo( - (props) => { - const { className, createdAt, slots, title, description, ...rest } = props; - - const { actions, tags, userAvatar, } = slots; - - return ( - - - {title} -
    - } - subheader={tags} - disableTypography - /> - - - {description} - - - - {userAvatar} - - - - ); - } -); diff --git a/src/entities/users/@x/activities.ts b/src/entities/users/@x/activities.ts new file mode 100644 index 00000000..8ede32c1 --- /dev/null +++ b/src/entities/users/@x/activities.ts @@ -0,0 +1 @@ +export { userSchema } from '../models'; diff --git a/src/entities/users/@x/rooms.ts b/src/entities/users/@x/rooms.ts new file mode 100644 index 00000000..f6d3228c --- /dev/null +++ b/src/entities/users/@x/rooms.ts @@ -0,0 +1 @@ +export { userIdSchema } from '../models'; diff --git a/src/entities/users/@x/tasks.ts b/src/entities/users/@x/tasks.ts new file mode 100644 index 00000000..8ede32c1 --- /dev/null +++ b/src/entities/users/@x/tasks.ts @@ -0,0 +1 @@ +export { userSchema } from '../models'; diff --git a/src/entities/users/index.ts b/src/entities/users/index.ts index 76671b44..84b005ff 100644 --- a/src/entities/users/index.ts +++ b/src/entities/users/index.ts @@ -1,3 +1,3 @@ export * from './ui'; export * from './lib'; -export * from './model'; +export * from './models'; diff --git a/src/entities/users/lib/index.ts b/src/entities/users/lib/index.ts index b5390675..77a98136 100644 --- a/src/entities/users/lib/index.ts +++ b/src/entities/users/lib/index.ts @@ -1,2 +1,2 @@ -export * from './useSearchedUsers'; -export * from './useUsersInRoom'; +export * from './use-users'; +export * from './use-members'; diff --git a/src/entities/users/lib/use-members.ts b/src/entities/users/lib/use-members.ts new file mode 100644 index 00000000..f3a7fc77 --- /dev/null +++ b/src/entities/users/lib/use-members.ts @@ -0,0 +1,7 @@ +import { useMolecule } from 'bunshi/react'; + +import { MembersModel, membersModel } from '../models'; + +export const useMembers = (): MembersModel => { + return useMolecule(membersModel.Molecule); +}; diff --git a/src/entities/users/lib/use-users.ts b/src/entities/users/lib/use-users.ts new file mode 100644 index 00000000..06fdec8c --- /dev/null +++ b/src/entities/users/lib/use-users.ts @@ -0,0 +1,9 @@ +import { useMemo } from 'react'; + +import { UsersModel, usersModel } from '../models'; + +// @todo rename to useUsersSearch +// @todo Move to features layer +export const useUsers = (): UsersModel => { + return useMemo(usersModel.Molecule, []); +}; diff --git a/src/entities/users/lib/useSearchedUsers.ts b/src/entities/users/lib/useSearchedUsers.ts deleted file mode 100644 index c8606352..00000000 --- a/src/entities/users/lib/useSearchedUsers.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useUnit } from 'effector-react'; - -import { searchUserModel } from '../model'; - -export const useSearchedUsers = () => { - return useUnit(searchUserModel.query); -}; diff --git a/src/entities/users/lib/useUsersInRoom.ts b/src/entities/users/lib/useUsersInRoom.ts deleted file mode 100644 index 48151d89..00000000 --- a/src/entities/users/lib/useUsersInRoom.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { useUnit } from 'effector-react'; - -import { usersInRoomModel } from '../model'; - -export const useUsersInRoom = () => { - return useUnit(usersInRoomModel.query); -}; diff --git a/src/entities/users/model/index.ts b/src/entities/users/model/index.ts deleted file mode 100644 index c288a623..00000000 --- a/src/entities/users/model/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as usersInRoomModel from './users-in-room'; -export * as searchUserModel from './search-user'; diff --git a/src/entities/users/model/search-user.ts b/src/entities/users/model/search-user.ts deleted file mode 100644 index c56353a3..00000000 --- a/src/entities/users/model/search-user.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { createQuery } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createDomain, createEvent, sample } from 'effector'; -import { debounce } from 'patronum'; -import { Array } from 'runtypes'; - -import { SearchUsersQuery, user, User, usersApi } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { getStandardResponse, StandardResponse } from '@/shared/types'; - -const searchUserDomain = createDomain(); - -const handlerFx = searchUserDomain.effect< - SearchUsersQuery, - StandardResponse, - Error ->(usersApi.searchUsers); - -export const query = createQuery< - SearchUsersQuery, - StandardResponse, - Error, - StandardResponse, - User[] ->({ - initialData: [], - effect: handlerFx, - contract: runtypeContract(getStandardResponse(Array(user))), - mapData: extractData, -}); - -export const searchChanged = createEvent(); - -const debouncedSearchChanged = debounce({ - source: searchChanged, - timeout: 200, -}); - -sample({ - clock: debouncedSearchChanged, - fn: (username) => ({ username, }), - target: query.start, -}); diff --git a/src/entities/users/model/users-in-room.ts b/src/entities/users/model/users-in-room.ts deleted file mode 100644 index 6e7f17f8..00000000 --- a/src/entities/users/model/users-in-room.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { cache, createQuery, keepFresh } from '@farfetched/core'; -import { runtypeContract } from '@farfetched/runtypes'; -import { createDomain } from 'effector'; -import { interval } from 'patronum'; -import { Array } from 'runtypes'; - -import { membersApi, user, User } from '@/shared/api'; -import { extractData } from '@/shared/lib'; -import { - getStandardResponse, - InRoomParams, - StandardResponse -} from '@/shared/types'; - -const usersInRoom = createDomain(); - -const handlerFx = usersInRoom.effect(membersApi.getAll); - -export const query = createQuery< - InRoomParams, - StandardResponse, - Error, - StandardResponse, - User[] ->({ - initialData: [], - effect: handlerFx, - contract: runtypeContract(getStandardResponse(Array(user))), - mapData: extractData, -}); - -export const $ids = query.$data.map((users) => users.map((user) => user.id)); -export const $count = query.$data.map((users) => users.length); -export const $hasError = query.$error.map((error) => !!error); - -cache(query); - -keepFresh(query, { - triggers: [interval({ timeout: 5000, })], -}); diff --git a/src/entities/users/models/index.ts b/src/entities/users/models/index.ts new file mode 100644 index 00000000..2394146e --- /dev/null +++ b/src/entities/users/models/index.ts @@ -0,0 +1,2 @@ +export * from './members'; +export * from './users'; diff --git a/src/entities/users/models/members/index.ts b/src/entities/users/models/members/index.ts new file mode 100644 index 00000000..85553b78 --- /dev/null +++ b/src/entities/users/models/members/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as membersModel from './model'; diff --git a/src/entities/users/models/members/model.spec.ts b/src/entities/users/models/members/model.spec.ts new file mode 100644 index 00000000..7437f105 --- /dev/null +++ b/src/entities/users/models/members/model.spec.ts @@ -0,0 +1,94 @@ +import { take } from '@reatom/framework'; +import { getDefaultInjector } from 'bunshi'; +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; + +import { + TestCtx, + createTestCtx, + defaultRoom, + handlers, + members, + rooms, + server +} from '~/test-utils'; + +import { Molecule, Scope } from './model'; +import { MembersModel } from './types'; + + +describe('src/entities/users/models/members/model.ts', () => { + let ctx: TestCtx; + let model: MembersModel; + + const createModel = (roomId = defaultRoom.id) => { + model = getDefaultInjector().get(Molecule, [Scope, roomId]); + }; + + beforeEach(() => { + ctx = createTestCtx(); + + vi.useFakeTimers(); + }); + + afterEach(async () => { + await vi.runOnlyPendingTimersAsync(); + + vi.useRealTimers(); + }); + + test('should create the same model for the same room id', () => { + createModel(); + + const anotherModel = model; + + createModel(); + + expect(anotherModel).toBe(model); + }); + + test('should create different models for different room ids', () => { + createModel(); + + const anotherModel = model; + + createModel(rooms[1].id); + + expect(anotherModel).not.toBe(model); + }); + + test('should load members for passed room', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.membersAtom); + + await expect(take(ctx, model.membersAtom)).resolves.toStrictEqual(members); + + track.unsubscribe(); + }); + + test('should load indicate if members is being loaded', async () => { + createModel(); + + const track = ctx.subscribeTrack(model.membersAtom); + + expect(ctx.get(model.pendingAtom)).toBe(true); + + await take(ctx, model.membersAtom); + + expect(ctx.get(model.pendingAtom)).toBe(false); + + track.unsubscribe(); + }); + + test('should store error during loading', async () => { + createModel(); + + server.use(handlers.members.error.members); + + const track = ctx.subscribeTrack(model.membersAtom); + + await expect(take(ctx, model.errorAtom)).resolves.toBeInstanceOf(Error); + + track.unsubscribe(); + }); +}); diff --git a/src/entities/users/models/members/model.ts b/src/entities/users/models/members/model.ts new file mode 100644 index 00000000..d28ae4be --- /dev/null +++ b/src/entities/users/models/members/model.ts @@ -0,0 +1,62 @@ +import { + mapState, + reatomResource, + withCache, + withDataAtom, + withErrorAtom, + withRetry +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { createScope, molecule, use } from 'bunshi'; + +import type { RoomId } from '@/entities/rooms/@x/users'; + +import { membersApi } from '@/shared/api'; +import { constructName, mapStandardResponse, retryQuery } from '@/shared/lib'; + +import { Users } from '../users'; + +import { MembersModel } from './types'; + +export const Scope = createScope(-1); + +const modelName = 'users'; + +const storage = createMemStorage({ + name: modelName, +}); +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(storage); + +export const Molecule = molecule((): MembersModel => { + const roomId = use(Scope); + + const fetchMembers = reatomResource( + async (ctx) => { + return ctx.schedule(() => { + return membersApi.getAll({ roomId, }, ctx.controller.signal); + }); + }, + constructName(modelName, roomId.toString(), 'fetchMembers') + ).pipe( + withDataAtom([] as Users, mapStandardResponse), + withCache({ withPersist, }), + withRetry(), + withErrorAtom(undefined, { initState: null, }) + ); + + retryQuery({ + query: fetchMembers, + store: fetchMembers.dataAtom, + timeout: 5000, + }); + + return { + errorAtom: fetchMembers.errorAtom, + membersAtom: fetchMembers.dataAtom, + pendingAtom: fetchMembers.pendingAtom.pipe( + mapState((_ctx, state) => !!state) + ), + retry: fetchMembers.retry, + }; +}); diff --git a/src/entities/users/models/members/types.ts b/src/entities/users/models/members/types.ts new file mode 100644 index 00000000..232576de --- /dev/null +++ b/src/entities/users/models/members/types.ts @@ -0,0 +1,16 @@ +import { Action, Atom } from '@reatom/framework'; + +import { StandardResponse } from '@/shared/types'; + +import { Users } from '../users'; + +export interface CreateMembersModelParams { + readonly roomId: number; +} + +export interface MembersModel { + readonly membersAtom: Atom; + readonly pendingAtom: Atom; + readonly errorAtom: Atom; + readonly retry: Action<[after?: number], Promise>>; +} diff --git a/src/entities/users/models/users/index.ts b/src/entities/users/models/users/index.ts new file mode 100644 index 00000000..44d5b590 --- /dev/null +++ b/src/entities/users/models/users/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as usersModel from './model'; diff --git a/src/entities/users/models/users/model.ts b/src/entities/users/models/users/model.ts new file mode 100644 index 00000000..366cc28d --- /dev/null +++ b/src/entities/users/models/users/model.ts @@ -0,0 +1,69 @@ +import { + action, + atom, + reatomResource, + withCache, + withDataAtom, + withErrorAtom, + withRetry +} from '@reatom/framework'; +import { createMemStorage, reatomPersist } from '@reatom/persist'; +import { createScope, molecule, use } from 'bunshi'; + +import { usersApi } from '@/shared/api'; +import { constructName, mapStandardResponse } from '@/shared/lib'; + +import { FetchUsersParams, Users, UsersModel } from './types'; + + +const modelName = 'users'; + +// eslint-disable-next-line @reatom/reatom-prefix-rule +const withPersist = reatomPersist(createMemStorage({ name: modelName, })); + +export const Scope = createScope(undefined); + +export const Molecule = molecule((): UsersModel => { + use(Scope); + + const paramsAtom = atom( + {}, + constructName(modelName, 'paramsAtom') + ); + + const fetch = reatomResource( + (ctx) => { + const params = ctx.spy(paramsAtom); + + return ctx.schedule(() => { + return usersApi.getUsers(params, ctx.controller.signal); + }); + }, + constructName(modelName, 'fetch') + ).pipe( + withDataAtom([] as Users, mapStandardResponse), + withCache({ withPersist, }), + withRetry(), + withErrorAtom(undefined, { initState: null, }) + ); + + const changeParams = action( + (ctx, params: FetchUsersParams) => { + paramsAtom(ctx, params); + }, + constructName(modelName, 'changeParams') + ); + + const { dataAtom: usersAtom, errorAtom, } = fetch; + const pendingAtom = atom( + (ctx) => !!ctx.spy(fetch.pendingAtom), + constructName(modelName, 'pendingAtom') + ); + + return { + usersAtom, + pendingAtom, + changeParams, + errorAtom, + }; +}); diff --git a/src/entities/users/models/users/types.ts b/src/entities/users/models/users/types.ts new file mode 100644 index 00000000..e4f09954 --- /dev/null +++ b/src/entities/users/models/users/types.ts @@ -0,0 +1,31 @@ +import { Action, Atom } from '@reatom/framework'; +import zod from 'zod'; + +export const userSchema = zod + .object({ + id: zod.number(), + email: zod.string().email(), + username: zod.string(), + photo: zod.string().url().nullable(), + }) + .readonly(); +export const userIdSchema = userSchema.unwrap().shape.id; + +export interface User extends zod.infer {} +export type Users = User[]; +export type UserId = User['id']; + +export interface CreateUsersModel { + readonly name: string; +} + +export interface FetchUsersParams { + readonly username?: string | null; +} + +export interface UsersModel { + readonly usersAtom: Atom; + readonly pendingAtom: Atom; + readonly errorAtom: Atom; + readonly changeParams: Action<[params: FetchUsersParams], void>; +} diff --git a/src/entities/users/ui/index.ts b/src/entities/users/ui/index.ts index 6f07efa6..c9495609 100644 --- a/src/entities/users/ui/index.ts +++ b/src/entities/users/ui/index.ts @@ -1,5 +1,4 @@ export * from './template-user-list-item'; export * from './user-avatar'; -export * from './users-in-room-picker'; -export * from './user-search'; export * from './skeleton-user-list-item'; +export * from './users-picker'; diff --git a/src/entities/users/ui/skeleton-user-list-item/__snapshots__/ui.spec.tsx.snap b/src/entities/users/ui/skeleton-user-list-item/__snapshots__/ui.spec.tsx.snap new file mode 100644 index 00000000..9e85ad4d --- /dev/null +++ b/src/entities/users/ui/skeleton-user-list-item/__snapshots__/ui.spec.tsx.snap @@ -0,0 +1,51 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`src/entities/users/ui/skeleton-user-list-item/ui > should render skeleton list item 1`] = ` +
  • +
    + +
    + +
    +
    +
    +
    +

    + +

    +

    + +

    +
    +
  • +`; diff --git a/src/entities/users/ui/skeleton-user-list-item/index.ts b/src/entities/users/ui/skeleton-user-list-item/index.ts index db5f4ed9..5ecdd1f3 100644 --- a/src/entities/users/ui/skeleton-user-list-item/index.ts +++ b/src/entities/users/ui/skeleton-user-list-item/index.ts @@ -1,4 +1 @@ -export { - SkeletonUserListItem, - type SkeletonUserListItemProps -} from './skeleton-user-list-item'; +export * from './ui'; diff --git a/src/entities/users/ui/skeleton-user-list-item/skeleton-user-list-item.module.css b/src/entities/users/ui/skeleton-user-list-item/styles.module.css similarity index 100% rename from src/entities/users/ui/skeleton-user-list-item/skeleton-user-list-item.module.css rename to src/entities/users/ui/skeleton-user-list-item/styles.module.css diff --git a/src/entities/users/ui/skeleton-user-list-item/skeleton-user-list-item.module.css.d.ts b/src/entities/users/ui/skeleton-user-list-item/styles.module.css.d.ts similarity index 100% rename from src/entities/users/ui/skeleton-user-list-item/skeleton-user-list-item.module.css.d.ts rename to src/entities/users/ui/skeleton-user-list-item/styles.module.css.d.ts diff --git a/src/entities/users/ui/skeleton-user-list-item/ui.spec.tsx b/src/entities/users/ui/skeleton-user-list-item/ui.spec.tsx new file mode 100644 index 00000000..fbb30ecf --- /dev/null +++ b/src/entities/users/ui/skeleton-user-list-item/ui.spec.tsx @@ -0,0 +1,21 @@ +import { describe, expect, test } from 'vitest'; + +import { SkeletonUserListItem } from './ui'; + +import { RenderResult, render } from '~/test-utils'; + +describe('src/entities/users/ui/skeleton-user-list-item/ui', () => { + let wrapper: RenderResult; + + const createComponent = () => { + wrapper = render(); + }; + + const findListItem = () => wrapper.getByRole('listitem'); + + test('should render skeleton list item', () => { + createComponent(); + + expect(findListItem()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/users/ui/skeleton-user-list-item/skeleton-user-list-item.tsx b/src/entities/users/ui/skeleton-user-list-item/ui.tsx similarity index 93% rename from src/entities/users/ui/skeleton-user-list-item/skeleton-user-list-item.tsx rename to src/entities/users/ui/skeleton-user-list-item/ui.tsx index f33f69bd..2f7805c6 100644 --- a/src/entities/users/ui/skeleton-user-list-item/skeleton-user-list-item.tsx +++ b/src/entities/users/ui/skeleton-user-list-item/ui.tsx @@ -11,7 +11,7 @@ import * as React from 'react'; import { CommonProps } from '@/shared/types'; -import styles from './skeleton-user-list-item.module.css'; +import styles from './styles.module.css'; export interface SkeletonUserListItemProps extends CommonProps, ListItemProps {} diff --git a/src/entities/users/ui/template-user-list-item/__snapshots__/ui.spec.tsx.snap b/src/entities/users/ui/template-user-list-item/__snapshots__/ui.spec.tsx.snap new file mode 100644 index 00000000..ab51fe0a --- /dev/null +++ b/src/entities/users/ui/template-user-list-item/__snapshots__/ui.spec.tsx.snap @@ -0,0 +1,137 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`src/entities/users/ui/template-user-list-item/ui > should render actions into right slot > with actions slot 1`] = ` +
  • +
    +
    + +
    +
    +
    +

    + username +

    +

    + email@example.org +

    +
    +
    +
    + actions +
    +
    +
  • +`; + +exports[`src/entities/users/ui/template-user-list-item/ui > should render extra into right slot > with extra slot 1`] = ` +
  • +
    +
    + +
    +
    +
    +

    + username +

    +

    + email@example.org +

    +
    +
    + extra +
    +
  • +`; + +exports[`src/entities/users/ui/template-user-list-item/ui > should render list item for user 1`] = ` +
  • +
    +
    + +
    +
    +
    +

    + username +

    +

    + email@example.org +

    +
    +
  • +`; diff --git a/src/entities/users/ui/template-user-list-item/index.ts b/src/entities/users/ui/template-user-list-item/index.ts index 0bb2c865..5ecdd1f3 100644 --- a/src/entities/users/ui/template-user-list-item/index.ts +++ b/src/entities/users/ui/template-user-list-item/index.ts @@ -1,4 +1 @@ -export { - TemplateUserListItem, - type TemplateUserListItemProps -} from './template-user-list-item'; +export * from './ui'; diff --git a/src/entities/users/ui/template-user-list-item/template-user-list-item.module.css b/src/entities/users/ui/template-user-list-item/styles.module.css similarity index 100% rename from src/entities/users/ui/template-user-list-item/template-user-list-item.module.css rename to src/entities/users/ui/template-user-list-item/styles.module.css diff --git a/src/entities/users/ui/template-user-list-item/template-user-list-item.module.css.d.ts b/src/entities/users/ui/template-user-list-item/styles.module.css.d.ts similarity index 100% rename from src/entities/users/ui/template-user-list-item/template-user-list-item.module.css.d.ts rename to src/entities/users/ui/template-user-list-item/styles.module.css.d.ts diff --git a/src/entities/users/ui/template-user-list-item/ui.spec.tsx b/src/entities/users/ui/template-user-list-item/ui.spec.tsx new file mode 100644 index 00000000..14de2260 --- /dev/null +++ b/src/entities/users/ui/template-user-list-item/ui.spec.tsx @@ -0,0 +1,42 @@ +import { describe, expect, test } from 'vitest'; + +import { RenderResult, defaultUser, render } from '~/test-utils'; + +import { Slots } from '@/shared/types'; + +import { TemplateUserListItem } from './ui'; + +describe('src/entities/users/ui/template-user-list-item/ui', () => { + let wrapper: RenderResult; + + const createComponent = (slots?: Slots<'actions' | 'extra'>) => { + wrapper = render( + + ); + }; + + const findListItem = () => wrapper.getByRole('listitem'); + + test('should render list item for user', () => { + createComponent(); + + expect(findListItem()).toMatchSnapshot(); + }); + + test('should render actions into right slot', () => { + createComponent({ actions:
    actions
    , }); + + expect(findListItem()).toMatchSnapshot('with actions slot'); + }); + + test('should render extra into right slot', () => { + createComponent({ extra:
    extra
    , }); + + expect(findListItem()).toMatchSnapshot('with extra slot'); + }); +}); diff --git a/src/entities/users/ui/template-user-list-item/template-user-list-item.tsx b/src/entities/users/ui/template-user-list-item/ui.tsx similarity index 66% rename from src/entities/users/ui/template-user-list-item/template-user-list-item.tsx rename to src/entities/users/ui/template-user-list-item/ui.tsx index 297d9d13..7d2ea9a0 100644 --- a/src/entities/users/ui/template-user-list-item/template-user-list-item.tsx +++ b/src/entities/users/ui/template-user-list-item/ui.tsx @@ -6,34 +6,24 @@ import { ListItemText } from '@mui/material'; import cn from 'classnames'; -import * as React from 'react'; +import { FC } from 'react'; -import { User } from '@/shared/api'; import { CommonProps, Slots } from '@/shared/types'; +import { User } from '../../models'; import { UserAvatar } from '../user-avatar'; -import styles from './template-user-list-item.module.css'; +import styles from './styles.module.css'; export interface TemplateUserListItemProps extends CommonProps, - User, - Omit { + Pick, + Omit { readonly slots?: Slots<'actions' | 'extra'>; } -export const TemplateUserListItem: React.FC = ( - props -) => { - const { - username, - className, - photo, - email, - id: _id, - slots = {}, - ...rest - } = props; +export const TemplateUserListItem: FC = (props) => { + const { username, email, photo, className, slots = {}, ...rest } = props; return ( should render user avatar with passed photo 1`] = ` +
    + Shit-user +
    +`; diff --git a/src/entities/users/ui/user-avatar/index.ts b/src/entities/users/ui/user-avatar/index.ts index 82716fa6..0b55e245 100644 --- a/src/entities/users/ui/user-avatar/index.ts +++ b/src/entities/users/ui/user-avatar/index.ts @@ -1 +1 @@ -export { UserAvatar, type UserAvatarProps } from './user-avatar'; +export * from './user-avatar'; diff --git a/src/entities/users/ui/user-avatar/user-avatar.spec.tsx b/src/entities/users/ui/user-avatar/user-avatar.spec.tsx new file mode 100644 index 00000000..3de72448 --- /dev/null +++ b/src/entities/users/ui/user-avatar/user-avatar.spec.tsx @@ -0,0 +1,21 @@ +import { describe, expect, test } from 'vitest'; + +import { UserAvatar } from './user-avatar'; + +import { RenderResult, render, users } from '~/test-utils'; + +describe('src/entities/users/ui/user-avatar/user-avatar', () => { + let wrapper: RenderResult; + + const createComponent = () => { + wrapper = render(); + }; + + const findAvatar = () => wrapper.container.querySelector('div')!; + + test('should render user avatar with passed photo', () => { + createComponent(); + + expect(findAvatar()).toMatchSnapshot(); + }); +}); diff --git a/src/entities/users/ui/user-avatar/user-avatar.tsx b/src/entities/users/ui/user-avatar/user-avatar.tsx index f7c7be75..d47a9113 100644 --- a/src/entities/users/ui/user-avatar/user-avatar.tsx +++ b/src/entities/users/ui/user-avatar/user-avatar.tsx @@ -2,10 +2,11 @@ import AccountCircleIcon from '@mui/icons-material/AccountCircle'; import { Avatar, Tooltip } from '@mui/material'; import * as React from 'react'; -import { User } from '@/shared/api'; import { stringToColor } from '@/shared/lib'; import { CommonProps } from '@/shared/types'; +import { User } from '../../models'; + export interface UserAvatarProps extends CommonProps, Pick { diff --git a/src/entities/users/ui/user-search/index.ts b/src/entities/users/ui/user-search/index.ts deleted file mode 100644 index ca69807c..00000000 --- a/src/entities/users/ui/user-search/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UserSearch, type UserSearchProps } from './user-search'; diff --git a/src/entities/users/ui/user-search/user-search.tsx b/src/entities/users/ui/user-search/user-search.tsx deleted file mode 100644 index f069c8c8..00000000 --- a/src/entities/users/ui/user-search/user-search.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Autocomplete } from '@mui/material'; -import { useUnit } from 'effector-react'; -import * as React from 'react'; - -import { User } from '@/shared/api'; -import { CommonProps } from '@/shared/types'; -import { Field, FieldProps } from '@/shared/ui'; - -import { useSearchedUsers } from '../../lib'; -import { searchUserModel } from '../../model'; -import { TemplateUserListItem } from '../template-user-list-item'; - -export interface UserSearchProps extends CommonProps, FieldProps { - readonly onChange?: (user: User | null) => unknown; - readonly value?: User | null; -} - -export const UserSearch: React.FC = (props) => { - const { className, onChange, value, ...rest } = props; - const users = useSearchedUsers(); - const resetUsers = useUnit(searchUserModel.query.reset); - const searchChanged = useUnit(searchUserModel.searchChanged); - - const handleChange = (_: unknown, user: User | null) => { - onChange?.(user); - }; - - const onInputChange = (_: unknown, value: string) => { - if (value === '') { - resetUsers(); - - return; - } - searchChanged(value); - }; - - return ( - option.username} - onInputChange={onInputChange} - renderOption={(props, option) => ( - - )} - renderInput={(params) => } - /> - ); -}; diff --git a/src/entities/users/ui/users-in-room-picker/index.ts b/src/entities/users/ui/users-in-room-picker/index.ts deleted file mode 100644 index 2bfc70fd..00000000 --- a/src/entities/users/ui/users-in-room-picker/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { - UsersInRoomPicker, - type UsersInRoomPickerProps -} from './users-in-room-picker'; diff --git a/src/entities/users/ui/users-in-room-picker/users-in-room-picker.tsx b/src/entities/users/ui/users-in-room-picker/users-in-room-picker.tsx deleted file mode 100644 index 35bc34ac..00000000 --- a/src/entities/users/ui/users-in-room-picker/users-in-room-picker.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Autocomplete } from '@mui/material'; -import * as React from 'react'; - -import { User } from '@/shared/api'; -import { preparePickerHandler, preparePickerSelectedValue } from '@/shared/lib'; -import { CommonProps, PickerProps } from '@/shared/types'; -import { Field, FieldProps } from '@/shared/ui'; - -import { useUsersInRoom } from '../../lib'; -import { TemplateUserListItem } from '../template-user-list-item'; - -export type UsersInRoomPickerProps = CommonProps & - PickerProps & - Omit; - -export const UsersInRoomPicker: React.FC = React.memo( - (props) => { - const { onChange, value, className, multiple, limitTags, ...rest } = props; - const users = useUsersInRoom(); - - const changeHandler = preparePickerHandler( - { multiple, onChange, }, - 'id' - ); - - const selected = preparePickerSelectedValue( - { value, multiple, }, - users.data, - 'id' - ); - - return ( - user.username} - loading={users.pending} - renderOption={(params, option) => ( - - )} - renderInput={(params) => { - return ; - }} - limitTags={limitTags} - multiple={multiple} - /> - ); - } -); diff --git a/src/entities/users/ui/users-picker/index.ts b/src/entities/users/ui/users-picker/index.ts new file mode 100644 index 00000000..125767a7 --- /dev/null +++ b/src/entities/users/ui/users-picker/index.ts @@ -0,0 +1 @@ +export * from './users-picker'; diff --git a/src/entities/users/ui/users-picker/users-picker.tsx b/src/entities/users/ui/users-picker/users-picker.tsx new file mode 100644 index 00000000..dba456f5 --- /dev/null +++ b/src/entities/users/ui/users-picker/users-picker.tsx @@ -0,0 +1,78 @@ +import { Autocomplete } from '@mui/material'; +import { + type ComponentType, + type FC, + type HTMLAttributes, + type SyntheticEvent, + memo +} from 'react'; + +import { preparePickerHandler, preparePickerSelectedValue } from '@/shared/lib'; +import type { CommonProps, Fn, PickerProps } from '@/shared/types'; +import { Field, type FieldProps } from '@/shared/ui'; + +import type { User, UserId, Users } from '../../models'; +import { TemplateUserListItem } from '../template-user-list-item'; + +export type UsersPickerProps = CommonProps & + PickerProps & + Omit & { + readonly users: Users; + readonly loading?: boolean; + readonly onInputChange?: Fn<[event: SyntheticEvent, value: string], void>; + /** + * @default {@link TemplateUserListItem} + */ + readonly UserListItem?: ComponentType & User>; + }; + +export const UsersPicker: FC = memo((props) => { + const { + onChange, + value, + className, + multiple, + limitTags, + users, + onInputChange, + loading, + UserListItem = TemplateUserListItem, + ...rest + } = props; + + const handleChange = preparePickerHandler( + { + onChange, + multiple, + }, + 'id' + ); + const selected = preparePickerSelectedValue( + { + value, + multiple, + }, + users, + 'id' + ); + + return ( + member.username} + loading={loading} + onInputChange={onInputChange} + renderOption={(params, option) => ( + + )} + renderInput={(params) => { + return ; + }} + limitTags={limitTags} + multiple={multiple} + /> + ); +}); diff --git a/src/features/activities/activities-filters/filters.tsx b/src/features/activities/activities-filters/filters.tsx deleted file mode 100644 index 56988982..00000000 --- a/src/features/activities/activities-filters/filters.tsx +++ /dev/null @@ -1,190 +0,0 @@ -/* eslint-disable sonarjs/no-duplicate-string */ -import TuneIcon from '@mui/icons-material/Tune'; -import { Button } from '@mui/material'; -import cn from 'classnames'; -import { useUnit } from 'effector-react'; -import * as React from 'react'; -import { useTranslation } from 'react-i18next'; - -import { - ActivitiesActionsPicker, - ActivitiesSpheresPicker -} from '@/entities/activities'; -import { UsersInRoomPicker } from '@/entities/users'; - -import { usePreventDefault, useToggle } from '@/shared/lib'; -import { CommonProps } from '@/shared/types'; -import { DatePicker, FiltersPopover, Show } from '@/shared/ui'; - -import styles from './filters.module.css'; -import { form } from './model'; - -export interface ActivitiesFiltersProps extends CommonProps {} - -export const ActivitiesFilters: React.FC = (props) => { - const { className, } = props; - const { t, } = useTranslation('room-activities'); - - const [open, { toggleOff, toggleOn, }] = useToggle(); - const [reset, submit] = useUnit([form.resetValues, form.submit]); - - const onSubmit = usePreventDefault(() => { - submit(); - toggleOff(); - }); - - const onReset = () => { - reset(); - toggleOff(); - }; - - const titleT = t('actions.filter_activities.title'); - const submitT = t('actions.filter_activities.actions.submit'); - const resetT = t('actions.filter_activities.actions.reset'); - - const buttons = ( - <> - - - - ); - - return ( - } - slots={{ actions: buttons, }}> - {({ isPopup, }) => ( -
    - - - - - - {buttons} - - )} -
    - ); -}; - -const Action: React.FC = () => { - const { t, } = useTranslation('room-activities'); - - const label = t('actions.filter_activities.fields.action'); - - const actionIds = useUnit(form.fields.actionIds); - - return ( - - ); -}; - -const Spheres: React.FC = () => { - const { t, } = useTranslation('room-activities'); - - const label = t('actions.filter_activities.fields.spheres'); - const sphereIds = useUnit(form.fields.sphereIds); - - return ( - - ); -}; - -const Users: React.FC = () => { - const { t, } = useTranslation('room-activities'); - - const label = t('actions.filter_activities.fields.users'); - const activistIds = useUnit(form.fields.activistIds); - - return ( - - ); -}; - -const After: React.FC = () => { - const { t, } = useTranslation('common'); - - const label = t('fields.create_after'); - const after = useUnit(form.fields.after); - - return ( - - ); -}; - -const Before: React.FC = () => { - const { t, } = useTranslation('common'); - - const label = t('fields.create_before'); - const before = useUnit(form.fields.before); - - return ( - - ); -}; diff --git a/src/features/activities/activities-filters/index.ts b/src/features/activities/activities-filters/index.ts index 31b4a7ba..c4ef023a 100644 --- a/src/features/activities/activities-filters/index.ts +++ b/src/features/activities/activities-filters/index.ts @@ -1,2 +1,2 @@ -export * as activitiesFiltersModel from './model'; -export { ActivitiesFilters, type ActivitiesFiltersProps } from './filters'; +export type { OnFiltersChanged, ActivitiesFitlers } from './model'; +export * from './ui'; diff --git a/src/features/activities/activities-filters/lib/activities-filters-scope-provider.tsx b/src/features/activities/activities-filters/lib/activities-filters-scope-provider.tsx new file mode 100644 index 00000000..9ecacf81 --- /dev/null +++ b/src/features/activities/activities-filters/lib/activities-filters-scope-provider.tsx @@ -0,0 +1,18 @@ +import { ScopeProvider } from 'bunshi/react'; +import { useId, type FC, type PropsWithChildren } from 'react'; + +import { activitiesFiltersModel } from '../model'; + +export const ActivitiesFiltersScopeProvider: FC = ( + props +) => { + const { children, } = props; + + const id = useId(); + + return ( + + {children} + + ); +}; diff --git a/src/features/activities/activities-filters/lib/index.ts b/src/features/activities/activities-filters/lib/index.ts new file mode 100644 index 00000000..fe254c53 --- /dev/null +++ b/src/features/activities/activities-filters/lib/index.ts @@ -0,0 +1,2 @@ +export * from './activities-filters-scope-provider'; +export * from './use-activity-filters'; diff --git a/src/features/activities/activities-filters/lib/use-activity-filters.ts b/src/features/activities/activities-filters/lib/use-activity-filters.ts new file mode 100644 index 00000000..d712683a --- /dev/null +++ b/src/features/activities/activities-filters/lib/use-activity-filters.ts @@ -0,0 +1,19 @@ +import { useMolecule } from 'bunshi/react'; + +import { useReaction } from '@/shared/lib'; + +import { activitiesFiltersModel, type OnFiltersChanged } from '../model'; + +export interface UseActivityFiltersParams { + readonly onFiltersChanged?: OnFiltersChanged; +} + +export const useActivityFilters = (params: UseActivityFiltersParams = {}) => { + const { onFiltersChanged, } = params; + + const model = useMolecule(activitiesFiltersModel.Molecule); + + useReaction(model.onFiltersChanged, onFiltersChanged); + + return model; +}; diff --git a/src/features/activities/activities-filters/model.ts b/src/features/activities/activities-filters/model.ts deleted file mode 100644 index e3d05c34..00000000 --- a/src/features/activities/activities-filters/model.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { createDomain } from 'effector'; -import { createForm } from 'effector-forms'; - -import { GetActivitiesInRoomParams } from '@/shared/api'; - -const activitiesFiltersDomain = createDomain(); - -export interface ActivitiesFiltersForm - extends Required< - Omit - > {} - -export const form = createForm({ - fields: { - activistIds: { - init: [], - }, - after: { - init: null, - }, - before: { - init: null, - }, - sphereIds: { init: [], }, - actionIds: { init: [], }, - }, - domain: activitiesFiltersDomain, -}); diff --git a/src/features/activities/activities-filters/model/index.ts b/src/features/activities/activities-filters/model/index.ts new file mode 100644 index 00000000..d561d47e --- /dev/null +++ b/src/features/activities/activities-filters/model/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * as activitiesFiltersModel from './model'; diff --git a/src/features/activities/activities-filters/model/model.ts b/src/features/activities/activities-filters/model/model.ts new file mode 100644 index 00000000..db7287f4 --- /dev/null +++ b/src/features/activities/activities-filters/model/model.ts @@ -0,0 +1,80 @@ +import { reaction, select } from '@reatom/framework'; +import { createScope, molecule, use } from 'bunshi'; + +import { FormFieldOptions, reatomForm } from '@reatom/form'; +// import { withSearchParamsPersist } from '@reatom/url'; + +import { constructName } from '@/shared/lib'; + +import type { + ActivitiesFiltersModel, + ActivitiesFitlers, + OnFiltersChanged +} from './types'; + +const modelName = 'activities-filters'; + +export const Scope = createScope(null); + +export const Molecule = molecule((): ActivitiesFiltersModel => { + use(Scope); + + const form = reatomForm( + { + actionIds: { initState: [] as ActivitiesFitlers['actionIds'], }, + activistIds: { + initState: [], + } as FormFieldOptions, + after: null as ActivitiesFitlers['after'], + before: null as ActivitiesFitlers['before'], + sphereIds: { initState: [] as ActivitiesFitlers['sphereIds'], }, + }, + { + resetOnSubmit: false, + name: constructName(modelName, 'form'), + } + ); + + const onFiltersChanged = reaction( + (ctx, onChange: OnFiltersChanged) => { + // Take some state + const filters = select(ctx, (ctx) => { + ctx.spy(form.submit.onFulfill); + ctx.spy(form.reset); + + return ctx.get(form.fieldsState); + }); + + // @todo Remove type assertion when parseAtoms types will be fixed + return onChange(filters as unknown as ActivitiesFitlers); + }, + constructName(modelName, 'onFiltersChanged') + ); + + /** + * @todo It does not work + */ + // form.fieldsState.pipe( + // withSearchParamsPersist('filters', { + // replace: true, + // parse: (v = '') => + // qs.parse(v, { parseArrays: true }) as any as ActivitiesFitlers, + // serialize: (v: ActivitiesFitlers) => + // queryString.stringify(v, { arrayFormat: 'brackets' }), + // }) + // ); + + const { submit, reset, } = form; + const { actionIds, activistIds, after, before, sphereIds, } = form.fields; + + return { + submit, + reset, + actionIds, + activistIds, + after, + before, + sphereIds, + onFiltersChanged, + }; +}); diff --git a/src/features/activities/activities-filters/model/types.ts b/src/features/activities/activities-filters/model/types.ts new file mode 100644 index 00000000..a6ef21c4 --- /dev/null +++ b/src/features/activities/activities-filters/model/types.ts @@ -0,0 +1,27 @@ +import type { Action, Reaction } from '@reatom/framework'; + +import type { FieldAtom } from '@reatom/form'; + +import type { ActivityActionId, ActivitySphereId } from '@/entities/activities'; +import type { UserId } from '@/entities/users'; + +export interface ActivitiesFitlers { + readonly actionIds: ActivityActionId[]; + readonly activistIds: UserId[]; + readonly after: string | null; + readonly before: string | null; + readonly sphereIds: ActivitySphereId[]; +} + +export type OnFiltersChanged = (filters: ActivitiesFitlers) => void; + +export interface ActivitiesFiltersModel { + readonly submit: Action; + readonly reset: Action; + readonly actionIds: FieldAtom; + readonly activistIds: FieldAtom; + readonly after: FieldAtom; + readonly before: FieldAtom; + readonly sphereIds: FieldAtom; + readonly onFiltersChanged: Reaction<[onChange: OnFiltersChanged], void>; +} diff --git a/src/features/activities/activities-filters/__snapshots__/filters.spec.tsx.snap b/src/features/activities/activities-filters/ui/filters/__snapshots__/filters.spec.tsx.snap similarity index 91% rename from src/features/activities/activities-filters/__snapshots__/filters.spec.tsx.snap rename to src/features/activities/activities-filters/ui/filters/__snapshots__/filters.spec.tsx.snap index 96eb9068..7db59583 100644 --- a/src/features/activities/activities-filters/__snapshots__/filters.spec.tsx.snap +++ b/src/features/activities/activities-filters/ui/filters/__snapshots__/filters.spec.tsx.snap @@ -1,10 +1,10 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`features/activities/activities-filters/filters > should render buttons to open filters form > closed filters 1`] = ` +exports[`features/activities/activities-filters/ui/filters.tsx > should render buttons to open filters form > closed filters 1`] = `
    should render form in @@ -185,15 +185,15 @@ exports[`features/activities/activities-filters/filters > should render form in autocapitalize="none" autocomplete="off" class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-1mv6xrr-MuiInputBase-input-MuiOutlinedInput-input" - id=":r6:" - name="spheres" + id=":r8:" + name="sphereIds" role="combobox" spellcheck="false" type="text" value="" />
    should render form in @@ -257,15 +257,15 @@ exports[`features/activities/activities-filters/filters > should render form in autocapitalize="none" autocomplete="off" class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-1mv6xrr-MuiInputBase-input-MuiOutlinedInput-input" - id=":r8:" - name="activists" + id=":ra:" + name="activistIds" role="combobox" spellcheck="false" type="text" value="" />